TP-Link Archer系列路由器是普联(TP-Link)公司的无线路由产品。TP-Link Archer A7/C7 (AC1750)的MIPS架构、固件版本为190726的路由器,其tdpServer服务存在命令注入漏洞,LAN侧的未授权攻击者可利用漏洞以root权限进行任意代码执行。该漏洞由Flashback团队(Pedro Ribeiro + Radek Domanski)在Pwn2Own Tokyo 2019活动中发现。
在TP-Link官网可下载对应版本固件:https://static.tp-link.com/2019/201908/20190816/Archer%20C7(US)_V5_190726.zip,尝试使用firmadyne工具运行固件:
但发现网络分配步骤失败:
进而运行时报错:
使用Qemu MIPS虚拟机加载固件运行,找到目标文件tdpServer并尝试执行:
发现执行出错。分析固件仿真启动和执行tdpServer失败的原因,估计是因为路由器在启动中,部分调用资源在其他硬件flash中,因而缺少资源导致失败,最好的方式不过为购买一台TP-Link Archer A7进行试验了。
tdpServer守护进程在本地0.0.0.0接口的UPD 20002端口监听,为TP-Link移动应用程序对路由器建立控制提供基础,守护进程与应用程序之间通过使用带有加密payload的UDP数据包通信,逆向分析得到数据包格式如下:
数据包的格式决定了守护进程提供的服务,例如type为0,守护进行将提供tdpd服务,使用特定的TETHER_KEY哈希值的数据包进行回复,但此处与漏洞无关;type为0xf0, 守护进行将提供onemesh服务, onemesh在许多TP-Link新固件中均引入了该项新技术,具体可参考( https://www.tp-link.com/us/onemesh/compatibility/)。
设备启动后,函数调用顺序为:tdpd_pkt_handler_loop()(地址:0x40d164)->监听端口20002接收到数据传递->tpdp_pkt_parser()(地址:0x40cfe0),tpdp_pkt_parser()函数伪码如下:
undefined4 FUN_0040cfe0(int iParm1,int iParm2,int iParm3,int *piParm4,int param_5)
{
byte bVar1;
uint uVar2;
undefined2 uVar5;
__pid_t _Var3;
int iVar4;
uint uVar6;
char *pcVar7;
char *pcVar8;
int local_c8 [42];
ushort local_20 [2];
int local_1c;
int local_18;
if (iParm1 != 0) {
iVar4 = FUN_0040d600();
if (iParm2 < iVar4) {
FUN_00403734("tdpdServer.c:709","recvbuf length = %d, less than hdr\'s 16",iParm2);
return 0xffffffff;
}
iVar4 = FUN_0040d620(iParm1);
if (iVar4 < 1) {
pcVar7 = "tdpdServer.c:716";
pcVar8 = "tdp pkt is too big";
}
else {
FUN_00403734("tdpdServer.c:719","tdp pkt length is %d",iVar4);
iVar4 = FUN_0040c9d0(iParm1,iVar4);
if (iVar4 < 0) {
return 0xffffffff;
}
if (*(char *)(iParm1 + 1) == 0) {
local_20[0] = 0;
if (iParm1 != 0) {
if (iParm3 == 0) {
return 0xffffffff;
}
if (piParm4 != (int *)0x0) {
bVar1 = *(byte *)(iParm1 + 6);
uVar2 = 1;
if ((bVar1 & 0x10) == 0) {
uVar2 = ((uint)bVar1 << 0x1a) >> 0x1f;
}
uVar6 = (uint)bVar1 & 1;
if (uVar2 == 0) {
uVar6 = 0;
}
if (uVar6 == 0) {
pcVar7 = "tdpdServer.c:837";
pcVar8 = "TDP flag error";
}
else {
if (*(short *)(iParm1 + 2) == 2) {
local_1c = 0;
local_18 = 0;
iVar4 = pipe((int *)&stack0xffffffe4);
if (iVar4 < 0) {
if (0 < local_1c) {
close(local_1c);
}
if (local_18 < 1) {
return 0xffffffff;
}
close(local_18);
return 0xffffffff;
}
_Var3 = fork();
if (_Var3 == -1) {
return 0xffffffff;
}
if (_Var3 == 0) {
close(local_1c);
local_20[0] = FUN_0040b804((void *)(iParm3 + 0x10),param_5);
write(local_18,local_20,2);
write(local_18,(void *)(iParm3 + 0x10),(uint)local_20[0]);
close(local_18);
/* WARNING: Subroutine does not return */
exit(0);
}
close(local_18);
wait((void *)0x0);
read(local_1c,local_20,2);
read(local_1c,(void *)(iParm3 + 0x10),(uint)local_20[0]);
close(local_1c);
uVar5 = *(undefined2 *)(iParm1 + 2);
}
else {
local_20[0] = FUN_0040b7d8(iParm3 + 0x10);
uVar5 = *(undefined2 *)(iParm1 + 2);
}
*(undefined2 *)(iParm3 + 2) = uVar5;
*(byte *)(iParm3 + 6) = *(byte *)(iParm1 + 6) & 0xfe | 2;
*(undefined *)(iParm3 + 7) = 1;
*(ushort *)(iParm3 + 4) = local_20[0];
*(undefined4 *)(iParm3 + 8) = *(undefined4 *)(iParm1 + 8);
iVar4 = FUN_0040cb20(iParm3);
if (-1 < iVar4) {
*piParm4 = iVar4;
return 0;
}
pcVar7 = "tdpdServer.c:844";
pcVar8 = "TDP encode pkt error";
}
FUN_00403734(pcVar7,pcVar8);
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课