首页 > 焦点 > > 内容页

CVE-2020-10882&&tdpServer分析

2023-06-28 13:40:06 来源:哔哩哔哩 分享到:

为什么会对一个几年前的漏洞进行分析呢,因为在HITP2023AMS会议上,看到一个关于TP-Link的tdpServer的json堆栈溢出(/2023/04/24/hitbams-your-not-so-home-office-soho-hacking-at-pwn2own/)所以我看了关于这个服务前几年的漏洞存在一个命令注入,这个命令注入是在pwn2own-tokyo由Flashback团队发现的(/blog/2020/4/6/exploiting-the-tp-link-archer-c7-at-pwn2own-tokyo)关于漏洞影响的版本可以访问链接。

下面就是正文,对原文中一些没有详细展开的函数点进行了分析,获取固件后解开后寻找/usr/bin/tdpServe直接给Ghidra进行分析


(资料图片)

recvfrom()

第一行,调用了recvfrom()接收UDP数据,获取UDP_data后调用tdpd_pkt_parser()

tdpd_pkt_parser()

这个函数有一下几个点

第十一行判断接收的数据长度不小于0x10,也就是16.

并且在15行tdp_get_pkt_len()函数,判断请求头中设置的长度不大于0x410

在这个函数里tdpd_pkt_sanity_checks()有多个判断,判断数据包中的第一个字节是否为0x01,还进行了CRC32校验,和对第二个字节是否为0xf0.

30行判断了第二个字节是否是-0x10

进入漏洞分支vuln_func_branch()

tdp_get_pkt_len()

这个函数比较简单全部都在第七行,判断param_1不为空.*(ushort *)(param_1 + 4)因为是ushort获取两个字节,加上0x10的长度小于0x410,而这个param_1+4的位置是我们在数据包头设置的payload的长度,判断成功后会返回我们设置的长度,而不是0xffffffff.

tdpd_pkt_sanity_checks()

第12行判断了数据包中第一个字节是否为0x01

第20行进行了CRC32循环冗余校验,判断数据包是否完整会进行详细的分析,但是只对代码分析不会展开讲CRC32

26行判断了第二个字节是否是0xf0,即使这里能够通过也会在tdpd_pkt_parser函数的第30行进行判断是否等于-0x10进行判断,也就是0xf0,才能进入漏洞函数分支

CRC_32()

该函数进行了一些运算,本质上就是CRC32的校验,在写POC时可以直接使用python中的去生成curCheckSum,填充到数据包中.

在第8行判断了长度和内容不为空,重要的的操作都在第11和12行,第11行简单来说就是整个data有多少个字节就循环多少次,第12行中的DAT_00416e90就是一个校验用的数据表.

核心操作: uVar1 = *(uint *)(&DAT_00416e90 + ((*Data ^ uVar1) & 0xff) * 4) ^ uVar1 >> 8;

先运行了*Data ^ uVar1获取了Data中的第一个字节和uVar1进行异或,在第一次进入函数uVar1的值为0xffffffff,在循环完成一次后uVar1会被重新赋值为上一次的结果

完成第一步的操作后将和0xff进行逻辑与操作并乘4,假设现在的通过运行算后生成了一个叫NewData的指针

*(uint *)(&DAT_00416e90 + NewData) ^ uVar1 >> 8现在的公式是这个样子的,因为uint类型会从指针的位置获取4个字节,根据运算符的优先级会先运行uVar1 >> 8在将从DAT_00416e90获取的数据和uVar1 >> 8的结果进行异或生成我们的新的uVar1,并进入下一次循环.

一下是python对这个操作的还原,值得注意的是在最后的生成的值由于 C 语言中整数类型的表示方式是使用补码,所以我们在python中还原校验是一个负数我们需要将他转换为无符号整数,当然如果你直接使用就不需要考虑这个了,在最后都需要将结果打包成一个32位大端的字节串才能够拼接Payload

vuln_func_branch()

在第12中FUN_0040e074函数中获取了config中的配置可以参考openwrt在没有实体机的情况下需要去添加配置文件

20行获取请求头中第三四个字节并减一,去switch我们需要到53行所以需要将请求头设为7

48行对请求头中的第7个字节&1不等于0,所以需要将第7个字节设为1

vuln_func()

这个函数太多了就给出关键位置

第一个data_decrypt,对data进行解密,AES加密CBC模式

通过对每一个json键值解析,并赋值并且所有的数据包都不能为空

就是漏洞点了snprintf拼接slave_mac的值,只需要闭合命令就可以在system中执行了,闭合的方法:

主要看一下data_decrypt里面关键函数FUN_0040ade0

end

POC

要注意的是在这个简单的POC中我们,并没有获取shell只是根目录生成了一个叫xxx的文件

也没有写自动更改第42行,如果更改我们payload长度也需要对第42行进行更改,payload的长度在第33行输出出来了

如果我们想要使用我们自己写的CRC32校验的话需要更改第57行

在非实体机运行tdpserver,还需要启动UBUS守护进程ubusd,否则就不会攻击成功

标签:
x 广告
x 广告

Copyright ©  2015-2022 南极科普网版权所有  备案号:粤ICP备2022077823号-13   联系邮箱: 317 493 128@qq.com