Tenda AC15栈溢出漏洞(CVE-2018-18708)
CVE-2018-18708
漏洞报告
漏洞基本信息
| 项目 | 内容 |
|---|---|
| 漏洞名称 | 多款Tenda产品httpd 缓冲区错误漏洞 |
| 厂商 | 腾达 (Tenda) |
| CNNVD编号 | CNNVD-201810-1339 |
| 危害等级 | 高危 |
| CVE编号 | CVE-2018-18708 |
| 漏洞类型 | — |
| 收录时间 | 2018-10-30 |
| 更新时间 | 2018-10-31 |
固件下载地址: AC15升级软件 - 腾达Tenda官方网站
环境搭建
我们下载得到的是一个zip文件,解压,然后binwalk获取固件,先查找一下发现有httpd程序,dhttpd是开发板,然后是看看init,发现有个启动必须项,这个是启动路由器会执行的,但是我们启动的只是单独的web服务,所以要记得补上cp -rf /webroot_ro/* webroot/,不然可能会出现问题
1 | [18:10:57] ~/桌面/固件/Tenda AC15(2018)/_US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin.extracted/squashfs-root |
然后是先将qemu-arm-static移到当前目录,启动,发现lib出问题了,设置一下主目录就可以了,但是我们发现程序卡在了这个位置,gdb连接一下
1 | .bin.extracted/squashfs-root |
找一下busybox然后看一下架构,发现是小端序arm架构
1 | [18:25:39] ~/桌面/固件/Tenda AC15(2018)/_US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin.extracted/squashfs-root |
然后是gdb-multiarch连接,记得设置架构之类的,target连接发现ni下去程序会卡在一处地方一直做循环
然后IDA打开看看,直接寻找welcome字符的位置,发现是作用在sub_2E420,打开看看
sub_2E420:
1 | int __fastcall sub_2E420(int a1, int a2) |
发现问题出现在这里,keypatch改一下就好了
然后保存重新上传启动
1 | sudo brctl addbr br0 |
然后有个ip,打开浏览器,成功了
漏洞分析
漏洞报告说formSetMacFilterCfg是漏洞点,看一下
formSetMacFilterCfg
1 | int __fastcall formSetMacFilterCfg(int a1) |
sub_C10D0:就是要返回0使其进入到else函数部分,所以要将参数设置为white
1 | int __fastcall sub_C10D0(const char *a1) #a1->macFilterType参数 |
sub_C14DC:
1 | int __fastcall sub_C14DC(int a1, const char *a2) |
sub_C17A0:
1 | int __fastcall sub_C17A0(const char *a1, const char *a2, int a3) |
sub_C24C0:
1 | int __fastcall sub_C24C0(const char *a1, char *a2) |
漏洞验证
简单地说,就是strcpy(a2 + 32, a1),a1->deviceList参数,a2+32->v12,所以我们的目的就是要让函数进入到这里执行这个片段,而我们一步步分析,很明显,两个条件,第一个是macFilterType=white,第二个就是大量的垃圾数据,但是记得加上“\r”(13),但是其实还有个隐藏的条件,因为当我的请求不带上cookies的话会被拒绝,这是AC6型号所不同的
poc:测试溢出大小版
1 | import requests |
也是成功了,发现溢出长度是176
1 | ───────────────────────[ DISASM / arm / set emulate on ]──────────────────────── |
构造ROP链
计算偏移
正常漏洞这样子就结束了,但是可以试试看提权
但是我们直接看vmmap,发现没有是没有什么有用的数据
但是,我们知道程序是用libc.so.0
我们直接找strcmp函数的plt地址是0x3e010
然后设置断点,发现0xff5ca010是strcmp的地址,所以libc_base=0xff58c000
1 | pwndbg> c |
这里补充一下:
r0寄存器是用来传递第一个参数,如system("/bin/sh")的/bin/sh的地址
r3是通用寄存器,存储system的地址
pc:指的是程序计数器,指向下一条要执行的指令地址
CPSR的T位作用:CPSR寄存器的T位(Thumb模式标志位)决定CPU执行模式:T=0:执行ARM指令(4字节对齐)。T=1:执行Thumb指令(2字节对齐),简单地说,就是将地址+T,
1 | pwndbg> p/t $cpsr |
构造
1 | ROPgadget --binary ./lib/libc.so.0 --only "pop"| grep r3 |
所以payload=b'a'*176+p32(gadget1)+p32(system)+p32(gadget2)+p32(bin_sh)
过程:
首先是溢出到gadget1,然后sp移动到system处,执行pop r3,pc,就是先将system地址给到r3,然后将gadget2给到pc,所以接下来是执行pc指向的gadget2,此时sp指向bin_sh,然后是执行gadget2,先将bin_sh给到r0,然后条转到r3也就是system执行
1 | payload = b"A"*176 # 填充到返回地址 |
exp:
这里我用的是puts来验证,因为可能是qemu用户态模式下的缺陷,如果用的是system的话,chroot的那个终端部分会死机,就是卡住了,输入什么都没有反应,但是换成puts执行成功说明rop构造成功了
1 | from pwn import * |
成功了