0x00 前情提要
嗯,没想到前几分钟还在写更新计划的我,现在已经在写这篇文字了。。(实际上是因为这个漏洞本人之前就已经分析复现过了,只差最后调试漏洞的过程,刚刚写完更新计划,想着要不现在就把这个也顺便写一下吧,我怕之后太懒了就给直接鸽了就不太好、、)
首先是为什么突然会关注到这个漏洞呢,事情起源于本人对于校园网的不满,我们校园网如果连WIFI的话,限速2MB/s(在哪都一样,在教学楼你可能甚至还连不上),打着打着游戏突然给你断了也是常有的事(一句话概括就是太垃圾)
然后为了改善一下我的上网体验(当然,是在宿舍),我就得购置一款路由器,而为了应付校园网的认证,还必须修改路由器固件,最后选择了红米的AC2100这款路由器。
关于这款路由器的刷写固件方法,百度一下基本上都是同一种,使用近期pppd爆出的一个存在长达17年的漏洞Poc来反弹shell,然后使用mtd命令进行Bootloader刷入工作,之后通过bootloader刷写自己的固件。
而这个漏洞就是本文的主题——CVE-2020-8597。
该漏洞 CVSS 评分 9.8,影响软件版本跨度长达17年。攻击者可以通过特制的流量包,远程攻击开放 PPPD 服务的服务器。因为 PPPD 通常以root(unix最高权限)运行,攻击成功可完全取得服务器控制权限。
CVE-2020-8597: PPPD 远程代码执行漏洞通告
0x01 漏洞原理
这个漏洞属于栈溢出漏洞,由于pppd属于开源软件,我们直接来看源码
漏洞点位于EAP-MD5数据包的处理过程(具体为eap_request和eap_response函数)
从上图中我们可以看到,vallen是从数据包里提取的数据,属于用户可控变量
而问题出在第二个if判断上,这个判断会必定不成立,会进入else分支,因而我们可以通过控制栈来控制程序执行流。
而通常pppd运行在路由器等网络终端设备,通常不支持或不积极开启NX保护,我们可以直接把shellcode写入到栈来执行。
0x02 EAP-MD5数据包格式
由于漏洞出现在pppd对于EAP-MD5的处理里面,所以我们需要先了解一下数据包的格式以便后续漏洞利用工作(对于协议的具体用途并非本文重点,这里不进行介绍,有兴趣的自信查找相关资料)。
如图所示,我们主要利用的就是最下面的Data区域
源码中vallen=EAP-MD5的Size,len=EAP的Length-6
0x03 Mips架构
这里由于路由器是Mips架构的,我们需要知道一点Mips的知识(这里博主其实也是现学现卖,详细的不懂。。)
首先是Mips本身不支持NX保护(前文有提到)
然后就是寄存器主要分为四组,s组寄存器在过程调用中需保存,而t组不用,v0-v1寄存器用作返回值,a0-a3则用来传参。间接跳转则通常由$t9寄存器实现。
指令部分,jr指令相当于x86的jmp指令,jalr则是相当于x86的call指令。
还有就是关于shellcode直接写入到栈执行,在Mips上有一个坑需要注意一下
因为 MIPS 流水线指令集的特点,存在 cache incoherency 的特性,需要手动调用 sleep 函数,将数据区刷新到指令区当中去,从而可以正常执行 shellcode。
固件安全之MIPS架构栈溢出利用技巧
0x04 静态分析
从路由器上提取pppd和libuClibc,使用IDA进行静态分析
这里由于有源码我们可以直接对着源码对变量名、函数名进行初步还原
这里不知道是不是编译器直接给优化掉了连第二个if都没有,直接就是内存复制
由于函数末端有设置寄存器值的操作,我们可以直接拿来使用
这里我们构造一条rop链,首先调用Sleep(1),然后跳到栈执行shellcode
对于Mips的Gadget查找,这里直接使用IDA的一个插件mipsrop,注意安装的时候要使用里面的install.py
我们首先找一条用来调用Sleep(1)的Gadget,先设置a0,然后jr跳过去执行,具体通过mipsrop.find("move $a0,")
命令查找
返回结果中选一条jr的即可,之后将s0覆盖为sleep函数地址,s1覆盖为1即可
然后我们将ra寄存器覆盖为libc里的一些通用Gadget,我个人喜好直接在定位到sigaction函数然后找引用
基本上任选一条都有以上类似的结构,这里我们只需要把s5覆盖为我们之前找的那条Gadget的地址,然后s3为栈地址即可
0x05 Exp编写
这里为了节省时间我直接用了网上的版本进行魔改
具体shellcode直接上网找现成的反弹shell即可,比如这个
0x06 漏洞利用
这里因为之前用来复现的路由器,博主不小心把Bootloader刷没了,所以看还在7天无理由时间内就直接退款了。。(其实还拆过机原本打算直接编程器刷回来的,但是一看flash用的是nand我就告辞了)
(这里其实也没什么好说的,网上一堆教程,不过基本上没有提过具体原理)
这里就简略描述一下过程具体利用原理吧
首先,由于这个漏洞在于pppd对于eap-md5的处理函数里面,我们需要先模拟路由器于PPPoE服务器直接的通讯,这里直接用某大佬写的脚本,简单通过python实现了一个PPPoE服务器
我们Poc的作用是通过一个有问题的eap-md5数据包来攻击
0x07 真机调试
其实这一步骤应该在之前的,不过因为上述原因,我路由器退货了,等什么时候开学买回来之后看看有没有空补上吧(不过不出意外90%会鸽)
0x08 附件
基本上本文用到的文件我都传到我Github上了,要的自己去取即可
传送门:https://github.com/lakwsh/CVE-2020-8597
(另外,求Star!!求关注!!)