tp-link WR740漏洞复现

前言

本项目旨在复现TP-Link WR740路由器固件中的漏洞。通过对固件进行解包、扫描和分析,最终实现漏洞的验证。整个过程涉及工具的安装与使用、代码的逆向分析以及模拟环境的搭建与测试。

0.问题分析

TP-Link WR740路由器存在一个严重的安全漏洞,允许攻击者通过特定的HTTP请求执行任意命令。这个漏洞存在于httpd程序中,通过对usr和passwd参数的验证不足,攻击者可以利用默认凭证进行未授权访问并执行命令。

1.固件获取

2.binwalk解包

环境
binwalk安装

binwalk 安装

1
2
3
$ git clone https://github.com/ReFirmLabs/binwalk.git
$ cd binwalk
$ sudo python3 setup.py install

sasquatch工具支持对 非标准的SquashFS格式的文件镜像 进行解压

sasquatch 安装

1
2
3
4
$ sudo apt-get install build-essential liblzma-dev liblzo2-dev zlib1g-dev
$ git clone https://github.com/devttys0/sasquatch.git
$ cd sasquatch
$ ./build.sh

sasquatch patch

1
2
3
4
5
cd patches
wget https://github.com/devttys0/sasquatch/files/7776843/M1-Kali.patch.txt
patch patch0.txt M1-Kali.patch.txt
cd ..
./build.sh
binwalk解包

$ binwalk -Me wr740nv1_en_3_12_4_up.bin

3.firmwalker扫描

获取firmwalker:git clone https://github.com/craigz28/firmwalker.git

路由器Web相关URL的格式为:/web/userRpm/*

image-20240512124702425

http服务器为httpd,且httpd中包含较多关键字符串,考虑对其进行分析

image-20240512124803655

image-20240512125003782

image-20240512125036615

4.httpd反编译分析

使用IDA搜索passwd字符串,得到如下结果

第一个搜索结果仅有passwd,比较可疑,检查其引用。

在“passwd”附近还出现了“usr”字符串,以及“osteam”、“5up”两个意义不明的字符串,考虑将整个函数转换为C代码进行分析

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
int DebugResultRpmHtm(undefined4 param_1)

{
undefined4 *puVar1;
int iVar2;
short sVar8;
char *pcVar3;
char *pcVar4;
size_t sVar5;
ssize_t sVar6;
undefined4 *puVar7;
undefined4 uVar9;
undefined4 uVar10;
undefined4 uVar11;
undefined4 *puVar12;
undefined4 *puVar13;
int iVar14;
int iVar15;
undefined4 local_c30 [5];
undefined2 local_c1c [1526];
undefined4 *local_30;
undefined4 local_2c;
undefined4 local_28;

local_2c = 0x100;
local_28 = 0;
local_30 = local_c30;
httpStatusSet(param_1,0);
iVar14 = 0;
httpHeaderGenerate(param_1);
iVar15 = 0;
iVar2 = HttpAccessPermit(param_1);
if (iVar2 == 0) {
sVar8 = HttpDenyPage(param_1);
goto LAB_004816b4;
}
local_c30[0]._0_1_ = 0;
if (pty_started != 0) {
pcVar3 = (char *)httpGetEnv(param_1,&DAT_0051717c);
if (pcVar3 != (char *)0x0) {
iVar2 = strcmp(pcVar3,"exit");
if (iVar2 != 0) {
iVar2 = httpGetEnv(param_1,"usr");
if ((iVar2 != 0) && (iVar2 = httpGetEnv(param_1,"passwd"), iVar2 != 0)) {
pcVar4 = (char *)httpGetEnv(param_1,"usr");
iVar2 = strcmp(pcVar4,"osteam");
if (iVar2 == 0) {
pcVar4 = (char *)httpGetEnv(param_1,"passwd");
iVar2 = strcmp(pcVar4,"5up");
if (iVar2 == 0) goto LAB_004813f8;
}
}
puVar7 = local_c30;
puVar1 = (undefined4 *)"####User or Password not correct###\\n";
do {
puVar13 = puVar1;
puVar12 = puVar7;
uVar9 = puVar13[1];
uVar10 = puVar13[2];
uVar11 = puVar13[3];
*puVar12 = *puVar13;
puVar12[1] = uVar9;
puVar12[2] = uVar10;
puVar12[3] = uVar11;
puVar7 = puVar12 + 4;
puVar1 = puVar13 + 4;
} while (puVar13 + 4 != (undefined4 *)0x5171c0);
*(undefined2 *)(puVar12 + 5) = *(undefined2 *)(puVar13 + 5);
puVar12[4] = 0x2323235c;
goto LAB_00481600;
}
LAB_004813f8:
sVar5 = strlen(pcVar3);
write(pty,pcVar3,sVar5);
pcVar4 = strstr(pcVar3,"ping");
if ((pcVar4 != (char *)0x0) ||
((pcVar4 = strstr(pcVar3,"cat"), pcVar4 != (char *)0x0 &&
(pcVar3 = strchr(pcVar3,0x26), pcVar3 == (char *)0x0)))) {
write(pty,"&",1);
}
write(pty,&DAT_00512b9c,1);
}
taskDelay(10);
do {
sVar6 = read(pty,(void *)((int)local_c30 + iVar14),0x10);
iVar15 = iVar15 + 1;
if (sVar6 != 0x10) goto LAB_00481574;
iVar14 = iVar14 + 0x10;
} while (iVar15 != 0xa8);
sVar6 = 0;
LAB_00481574:
if (1 < sVar6 + 1U) {
iVar14 = sVar6 + iVar14;
}
*(undefined *)((int)local_c30 + iVar14) = 0;
while( true ) {
puVar7 = (undefined4 *)strstr((char *)local_c30,"\r\n");
if (puVar7 == (undefined4 *)0x0) break;
sVar5 = strlen((char *)((int)puVar7 + 2));
memmove(puVar7 + 1,(char *)((int)puVar7 + 2),sVar5 + 1);
*puVar7 = 0x5c725c6e;
}
}
LAB_00481600:
httpPrintf(param_1,
"<SCRIPT language=\"javascript\" type=\"text/javascript\">\nvar %s = new Array(\n",
"cmdResult");
httpPrintf(param_1,"\"%s\",\n",local_c30);
httpPrintf(param_1,"0,0 );\n</SCRIPT>\n");
HttpWebV4Head(param_1,0,0);
iVar14 = httpRpmFsA(param_1,"/userRpm/DebugResult.htm");
if (iVar14 == 2) {
return 2;
}
sVar8 = HttpErrorPage(param_1,10,0,0);
LAB_004816b4:
return (int)sVar8;
}

注意到此函数将http请求中usr、passwd字段分别与“osteam”、“5up”比较,并执行http中cmd字段的命令

通过write(pty,cmd,strlen(cmd))来模拟执行命令。伪终端(pseudo terminal,有时也被称为 pty)是指伪终端 master 和伪终端 slave 这一对字符设备。其中的 slave 对应 /dev/pts/目录下的一个文件,而 master 则在内存中标识为一个文件描述符(fd)。伪终端由终端模拟器提供,终端模拟器是一个运行在用户态的应用程序。可通过写pty文件执行指令。

用IDA Pro对httpd程序进行反编译分析。搜索关键字符串如passwd,并分析相关函数,发现漏洞点在于对usrpasswd字段的验证不足,且可以通过pty伪终端执行命令。

检查该函数调用情况,发现url绑定

5.模拟验证

环境

由于涉及分区挂载操作,FirmAE不能在WSL下运行。

FirmAE安装
1
2
3
$ git clone --recursive https://github.com/pr0v3rbs/FirmAE
$ ./download.sh
$ ./install.sh
模拟

先检查能否模拟

然后进行模拟

访问前面发现的url,根据提示输入默认账号密码,发现可以执行命令

6. 结论

通过对TP-Link WR740路由器固件的详细分析与模拟测试,成功复现了固件中的漏洞。本文展示了从固件获取、解包、扫描到漏洞分析和模拟验证的全过程,为进一步的安全研究提供了实践案例。

7. 参考文献

作者

Rye Song

发布于

2024-05-07

更新于

2024-07-14

许可协议