为什么会对一个几年前的漏洞进行分析呢,因为在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()
接收UDP数据,获取UDP_data后调用tdpd_pkt_parser()
这个函数有一下几个点
第十一行判断接收的数据长度不小于0x10,也就是16.
并且在15行tdp_get_pkt_len()函数,判断请求头中设置的长度不大于0x410
在这个函数里tdpd_pkt_sanity_checks()有多个判断,判断数据包中的第一个字节是否为0x01,还进行了CRC32校验,和对第二个字节是否为0xf0.
30行判断了第二个字节是否是-0x10
进入漏洞分支vuln_func_branch()
这个函数比较简单全部都在第七行,判断param_1不为空.*(ushort *)(param_1 + 4)
因为是ushort获取两个字节,加上0x10的长度小于0x410,而这个param_1+4
的位置是我们在数据包头设置的payload的长度,判断成功后会返回我们设置的长度,而不是0xffffffff.
第12行判断了数据包中第一个字节是否为0x01
第20行进行了CRC32循环冗余校验,判断数据包是否完整会进行详细的分析,但是只对代码分析不会展开讲CRC32
26行判断了第二个字节是否是0xf0,即使这里能够通过也会在tdpd_pkt_parser函数的第30行进行判断是否等于-0x10进行判断,也就是0xf0,才能进入漏洞函数分支
该函数进行了一些运算,本质上就是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
在第12中FUN_0040e074函数中获取了config中的配置可以参考openwrt在没有实体机的情况下需要去添加配置文件
20行获取请求头中第三四个字节并减一,去switch我们需要到53行所以需要将请求头设为7
48行对请求头中的第7个字节&1不等于0,所以需要将第7个字节设为1
这个函数太多了就给出关键位置
第一个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,否则就不会攻击成功
Copyright © 2015-2022 南极科普网版权所有 备案号:粤ICP备2022077823号-13 联系邮箱: 317 493 128@qq.com