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了。
这里过了之后,发现因为check_network一直在尝试访问br0网络,而br0不存在导致ip显示不正确,跳过方式就是直接建立网桥把名称为br0的绑定到自己的网卡名称上。
1 |
|
函数检查
根据已公布信息,直接找到R7WebsSecurityHandler函数,很明显sscanf就是漏洞函数了
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 |
|