前提
本次漏洞复现 所选择的设备为 Netgear R6400v2 固件版本为1.0.4.102
参照文章 https://bestwing.me/PSV-2020-0437-Buffer-Overflow-on-Some-Netgear-outers.html
固件下载地址 https://www.downloads.netgear.com/files/GDC/R6400v2/R6400v2-V1.0.4.102_10.0.75.zip
固件提取
这里下载到的固件是zip压缩文件 unzip解压后 发现需要被提取的文件格式是chk
其通常是程序或者工具生成的检查点或者状态文件
不过还是照常使用binwalk提取
binwalk -Me R6400v2-V1.0.4.102_10.0.75.chk |
漏洞挖掘
先使用firmwalker工具来大致的了解固件中可能存在的漏洞
./firmwalker.sh ../iot/_R6400v2-V1.0.4.102_10.0.75.chk.extracted/squashfs-root ../firmwalker.txt |
发现存在了telnet服务 联想到之前复现过的一个cve是通过越权开启telnet 同时存在硬编码的账密
不过这题是否存在这个问题 还需要后续的挖掘
先步入到usr/sbin目录中 查看该固件涉及到的协议
存在httpd和upnpd 其中upnpd所存在的漏洞相对较多 这里先重点分析一下
32位小端序的arm架构 使用ida32查看反汇编代码
自己看了main函数后 没发现什么端倪 于是查看了教程 发现是通过recvfrom函数来定位漏洞函数的
该函数基于套接字来传输 所以利用这个函数来查找可以由我们输入的数据引发的漏洞确实是一个好思路 学到了
依靠交叉索引定位到sub_1B0E0函数
这里可以往v50数组中读入0x1fff的数据 下面存在一个if判断
如果upnp_turn_on的值为1 并且输入的数据小于0x100字节 就可以进入sub_23FB0函数 v50数组作为a1参数
在该函数一开始 利用strncpy将a1的数据复制给了v39 同时v41指针指向v39
带着v42参数一起进入了sub_B9EC函数
这个函数用于在v41中查找v42字符串 同时返回v41包含该字串的下一个字节的地址
结合下面的代码 可以看出这里是在针对a1数组中的数据进行参数数值的提取
92行出现了一个新的函数sub_22D20
这个函数中也存在strncpy函数 观察一下拷贝的字节长度是否能够达到栈溢出
首先是在a1字符串里查找MX: 然后再次查找\r\n
同时对于位置进行了检测 确保\r\n位于MX:的后三个字节开外
strncpy函数复制字节的长度为 v5-(v4+3) 也就是靠\r\n来决定复制的长度
而v7数组的长度显然小于可以复制的长度 所以这里存在栈溢出
固件模拟
这里使用qemu来进行系统模拟
#!/bin/bash |
随后进入模拟机中配置eth0
ifconfig eth0 192.168.6.10 |
然后用scp传输squashfs-root文件夹到模拟机中
tar -cvf 1.tar ./squashfs-root |
随后挂载目录 准备运行upnp
mount -t proc /proc ./squashfs-root/proc |
直接运行upnpd发现并没有回显
这是因为NVRAM(非易失性RAM)用于存储路由器的配置信息 upnpd运行时需要用到其中部分的信息 在没有实体硬件的情况下 这里使用LD_PRELOAD环境变量来引导
这里使用这个项目来帮助我们搭建环境
https://github.com/therealsaumil/custom_nvram
这里直接使用项目中已经编译好的nvram.so文件
接下来执行下面指令 看看是否能够运行
LD_PRELOAD="/custom_nvram_r6250.so" ./usr/sbin/upnpd |
遇到了第二个报错 缺少libc.so.6
libc.so.0和libc.so.6是不同版本的c标准库 数字的区别在于版本号
这里直接更改名字 将libc.so.0复制一份并且修改为libc.so.6即可
mv ./lib/libc.so.0 ./lib/libc.so.6 |
可以看到这时候没有报错
但是这里fopen打开的文件目录显然不存在 所以自己创建目录后成功运行
还需要用到nvram.ini文件 在项目中有提到
按照下面这样配置nvram.ini
upnpd_debug_level=9 |
随后成功运行
环境搭建到这里就结束了 有一点疑惑的是查看的教程还需要/lib/libdl.so.0 但是本人没有遇到这个报错