TOTOLINK漏洞挖掘
学习路由器漏洞挖掘的知识有一段时间了,最常见的漏洞就是命令注入和栈溢出。前段时间正好分析了下TOTOLINK路由器,下面做一下分析过程的回顾。
为了后续cve提交不产生重复,同时快速的了解这款路由器,我选择从已有漏洞入手,通过cve-list查看存在的漏洞。
这里在搜索的时候,我是选择搜索当前分析版本 和 全版本的漏洞信息。这样查看的好处是,有些漏洞可能在其他版本里面已经提交了,但是在你分析的这个版本里面没有提交,通过对比分析,有机会快速收割。
比如下面的几个cve,就是在不同版本下的。函数名称都是setDeviceName,问题参数都是 devicename 和 devicemac
这里再插一嘴,cve-list 上面有些漏洞信息并不完整,比如漏洞没有指明具体的模块,查看的时候并不方便,这里可以使用search and replace工具根据函数名称定位到模块。
全版本搜索结果如下:
从全版本的搜索结果可以看出存在大量命令注入类型的漏洞,溢出类型的漏洞比较少。
找几个漏洞进去看一下,命令执行的漏洞基本都是system 函数,popen函数参数没有过滤导致的。溢出类型的漏洞基本都是 strcpy 导致的。
查看当前分析版本存在的漏洞
当前版本的漏洞基本都是以命令注入为主。
通过对已存在漏洞的查看,基本可以确定一下我们要分析的模块的范围:
1、\squashfs-root\lib\cste_modules\*
2、\squashfs-root\web_cste\cgi-bin\*
3、\squashfs-root\bin\*
下面就是一套常规的分析流程了
1、固件下载地址
https://www.totolink.net/home/menu/detail/menu_listtpl/download/id/170/ids/36.html
当前最新版本为V4.1.2cu.5247_B20211129,这里我们以V4.1.2cu.5050_B20200504 为例
2、binwalk 解压
3、利用ida逐个的对目标文件进行分析,主要通过ida的交叉引用功能查找system,execv,popen,strcpy,memcpy,sprintf等函数的使用,这里有些so 文件可能对这些函数进行了二次封装,在分析的时候也要注意这种函数的交叉引用情况。如:
命令注入漏洞:
一段时间的检索分析之后,排除掉cve-list中已经存在的漏洞情况,在\squashfs-root\bin\cloudupdate_check 程序中发现了命令注入点。
下面分析参数来源,判断是否可控。
system 函数的参数没有任何过滤直接执行,v13 来自于对v6 的snprintf,v6 来自于 对 a1 的websGetvar("magicid"),a1 是函数uci_cloudupdate_config 的参数。查看uci_cloudupdate_config 的交叉引用情况,进行栈回溯分析,
v12 来自于v9,v9来自于v5,v5来自于a2,a2 是 函数parse_upgserver_info 的参数,这里能看到一个“200 OK”,结合函数名称,可以猜测这里是对服务器返回的数据进行的解析处理,继续对parse_upgserver_info进行回溯分析
v19 的数据由recv 函数获取,这个v4 是个socket 描述符,由init_tcp_client返回。
查看init_tcp_client函数,这里地址转换函数使用了v0,v0 来自于byte_414180
通过对 来自于byte_414180 的交叉引用分析,得到服务器网址为"update.carystudio.com"
也就是说数据实际来自于服务端的返回数据,如果能够控制服务端的返回数据,也就可以执行命令。
路由器抓包:
1、因为需要获取服务器的返回值,需要抓取数据包,这里通过windows主机开启热点,启动路由器的中继模式连接主机热点,通过抓取主机流量的方式,过滤获得路由器的数据包
路由器数据包如下:
程序本身存在如下的一些校验,还需要修改mode字段以绕过校验
环境模拟步骤如下:
1、修改windows hosts文件,添加 192.168.0.112 update.carystudio.com 使得解析路径指向本地ip
2、本地开启80端口,等待连接,python脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import
socket
sSock
=
socket.socket()
sSock.bind((
'192.168.0.112'
,
80
))
sSock.listen(
1000
)
cSock,addr
=
sSock.accept()
if
(
True
):
str1
=
cSock.recv(
1024
)
print
(
"客户端说:"
+
str1.decode(
'utf-8'
))
str2
=
cSock.send(str2.encode())
cSock.close()
|
3、重启路由器
wireshark 抓取数据包内容如下
登陆后台可以发现,已成功写入文件/tmp/ActionMd5 和 /tmp/DlFileUrl
另:一般这种确定应用程序的运行时机的方式,都是正向分析启动项;如果是模块程序的话,cgi-bin这种的,就要分析服务端程序(httpd,nginx)的配置文件.
栈溢出漏洞:
栈溢出漏洞就比较多了,大都是strcpy函数调用时没有校验长度导致的,查找过程也就是通过ida 的交叉引用,查找strcpy,sprintf,memcpy等危险函数的调用,这里就不再赘述了。
红框里面的数据是没有提交cve的,但是是存在溢出的,因为没有办法泄露libc 的地址,无法进行进一步的利用,也就没再继续看了,感兴趣的小伙伴可以自己试试。
另:如果这里的程序是cgi程序,且你需要进行动态调试的话,可以先gdb 附加httpd ,再通过set follow-fork-mode child;catch exec,追踪子进程进行调试。
下面是这次挖掘提交的cve:
CVE-2022-29646,
CVE-2022-29645,
CVE-2022-29644,
CVE-2022-29643,
CVE-2022-29642,
CVE-2022-29641,
CVE-2022-29640,
CVE-2022-29639,
CVE-2022-29638