CVE-2019-7406

Catalpa 网络安全爱好者

re365 是 TP-Link 旗下的一款 WiFi 信号拓展器,IBM 安全研究员在此设备上面发现了一个严重的 RCE 漏洞,不需要身份验证,攻击者可以通过向设备发送畸形的 HTTP 数据包在设备上执行任意命令。

漏洞分析

首先去 TP-Link 官方网站下载固件 https://www.tp-link.com/uk/support/download/re365/#Firmware

应该下载 2018-06-05 释出的固件,最新版固件已经修复了此漏洞。

下载后解压出固件,可直接使用 binwalk 解压固件。通过查看 init 信息,发现系统启动之后会自动运行 /usr/bin/httpd 程序,这个程序应该是用于处理 HTTP 请求的,先查看一下基本信息:

1
httpd: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-, stripped

MIPS 小端序,直接使用 Ghidra 进行分析。

根据披露信息,可以定位到函数 httpRpmWmbParse,在第 89 行位置存在如下代码

1
2
3
4
5
6
7
8
9
10
11
12
if (iVar2 == 0) {
__haystack = (char *)httpGetEnv(param_1,"USER_AGENT");
iVar2 = 0;
do {
pcVar6 = strstr(__haystack,&DAT_004b11e0 + iVar2);
iVar2 = iVar2 + 0xf;
if (pcVar6 != (char *)0x0) {
PRINTF_ECHO("Mobile Agent: %s",__haystack);
DAT_004b3718 = 1;
goto LAB_0047e8e0;
}
} while (iVar2 != 0xd2);

和许多固件一样,这里会从当前环境变量中取得相应的数据,然后对其进行一系列操作。

首先从环境变量中取得 user-agent 字段,然后利用 strstr 函数判断其中是否存在某些字符串,例如

1
2
3
4
iPod
iPod touch
iPhone
Mobile Safari 等

如果存在这些字符串其中一个,就使用 PRINTF_ECHO 将其打印到终端

PRINTF_ECHO 函数如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void PRINTF_ECHO(char *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)

{
undefined4 local_res4;
undefined4 local_res8;
undefined4 local_resc;
char acStack268 [260];

local_res4 = param_2;
local_res8 = param_3;
local_resc = param_4;
memset(acStack268,0,0x100);
vsprintf(acStack268,param_1,&local_res4);
execFormatCmd("echo \"====>>>>%s\" > /dev/console \r\n",acStack268);
return;
}

Ghidra 的参数识别有一些异常,但是反编译结果是正确的,第一个参数是格式化字符串 “Mobile Agent: %s”,第二个参数是取得的 user-agent 字段。

接着调用 execFormatCmd 函数,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void execFormatCmd(char *param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4)

{
undefined4 local_res4;
undefined4 local_res8;
undefined4 local_resc;
char acStack268 [264];

local_res4 = param_2;
local_res8 = param_3;
local_resc = param_4;
vsprintf(acStack268,param_1,&local_res4);
FUN_0040b740(acStack268);
return;
}

此函数会利用 vfprintf 将外面传进来的参数放在 stack 268 中,然后调用函数 FUN_0040b740

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
int FUN_0040b740(int param_1)

{
__pid_t __pid;
undefined4 uVar1;
__pid_t _Var2;
int *piVar3;
int local_30;
char *local_2c;
undefined *local_28;
int local_24;
undefined4 local_20;
int local_18;

local_30 = 0;
if (param_1 == 0) {
uVar1 = 0;
}
else {
local_18 = param_1;
__pid = fork();
uVar1 = 0xffffffff;
if (__pid != -1) {
if (__pid == 0) {
local_2c = "sh";
local_24 = local_18;
local_28 = &DAT_004916fc;
local_20 = 0;
execve("/bin/sh",&local_2c,(char **)0x0);
/* WARNING: Subroutine does not return */
exit(0x7f);
}
do {
_Var2 = waitpid(__pid,&local_30,0);
if (_Var2 != -1) {
return local_30;
}
piVar3 = __errno_location();
uVar1 = 0xffffffff;
} while (*piVar3 == 4);
}
}
return uVar1;
}

直接使用 execve 拼接上面的命令然后执行,过程中不存在对参数的过滤。所以可以通过构造合适的 user-agent 字段来达到 RCE 的目的。

re365 的其他几个漏洞

细心的同学应该会发现,在函数 PRINTF_ECHO 以及后面的 execFormatCmd 都有 vfprintf 函数,但是在使用这些函数的时候没有检验一下源字符串的长度,因为 user-agent 是用户可控的,所以这里是存在栈溢出的。

另外在 /etc/shadow 文件中有以下数据

1
root:$1$GTN.gpri$DlSyKvZKMR9A9Uj9e9wR3/:15502:0:99999:7:::

感兴趣的可以自己搜索一下这段密码,设备默认应该是开放了带有密码的 telnet,得到这串密码的明文我们似乎就可以直接登录设备了。

  • Title: CVE-2019-7406
  • Author: Catalpa
  • Created at : 2020-02-29 00:00:00
  • Updated at : 2024-10-17 08:46:09
  • Link: https://wzt.ac.cn/2020/02/29/CVE-2019-7406/
  • License: This work is licensed under CC BY-SA 4.0.