小米路由器-逻辑漏洞学习笔记

小米路由器三个逻辑漏洞学习笔记

Posted by X1ng on December 16, 2020

B站上看的长亭实验室的hitcon演讲视频,记个笔记

视频分享的是对小米AX3600路由器的漏洞挖掘过程

攻击面分析

由于过于贫穷,又没有淘到N手路由器,只能贴一些ppt里的图

用nmap扫描到的开放端口

web server开放了 80/8080/8098/8999 四个端口,其所有web功能都是通过lua来实现的,而小米的lua解析器是经过加密的

获取固件

官网提供下载的已经更新,这是更新前的固件

由于固件是ubi文件系统,下载最新版本的ubi_reader

binwalk -Me binwalk -Me miwifi_r3600_firmware_5da25_1.0.17.bin
cd _miwifi_r3600_firmware_5da25_1.0.17.bin.extracted
ubireader_extract_images 2AC.ubi
cd ubifs-root/2AC.ubi
sudo unsquashfs ./img-1696626347_vol-ubi_rootfs.ubifs

在生成的squashfs-root目录下就是文件系统了

1.后台登陆绕过(CVE-2020-11959)

该路由器的webserver是由nginx启动的,在nginx的配置文件中找到第一个漏洞

漏洞产生的原因是在使用alias设置别名时少了一个”/”,造成的路径穿越漏洞

比如在GET /backup/log../file HTTP/1.1的时候,会替换成GET /tmp/syslogbackup/../file HTTP/1.1,但是由于nginx的限制,只能读取到tmp下的文件

由于没有调试环境来直接查看tmp目录下的文件,可以对整个文件系统中搜索”/tmp/”来查找tmp目录的文件或目录

发现找到的/tmp/messages目录下保存着日志,其中保存了明文Wi-Fi密码、pppoe的用户名密码等信息

而其中保存的stok string则是访问后台页面的token,利用stok string可以实现后台登录绕过

2.命令执行(CVE-2020-11960)

通过0day获取了调试环境(???

然后在后台发现有从备份恢复路由器的功能可以上传文件

对下载的备份文件进行分析,备份文件是一个.tar.gz格式文件,解压文件后得到一个.des.mbu文件,其中.des文件内容为一些描述信息、.mbu文件内容被加密

也就是说备份文件从上传到使用的过程为 上传->解压->解密->应用

进行尝试分析

  • 不能直接上传webshell,上传的文件会被保存在/tmp目录下并重命名为cfgbackup.tar.gz
  • 没有路径穿越问题
  • 由于不知道加密方法,也不能通过插入一些恶意字段到.mbu文件中来进行利用

对每一步异常情况进行尝试分析

  1. 上传失败:上传失败对路由器不造成任何影响
  2. 解压失败:只能上传.tar.gz格式的压缩包,解压不会存在什么问题,如果解压失败后上传的文件会被立刻删除
  3. 解密与应用失败:经过尝试,解压后的文件如果不能被正确的解析,压缩包会立刻被删除,但是解压后的文件会保留在文件系统中,所以可以在/tmp和/tmp的子目录下 上传内容完全可控、文件名必须包含mbu或des字符的文件

寻找上传文件的目标路径,可以找到的tmp目录下的子目录./spool/cron以及./dnsmasq.d可能可以利用

  • /tmp/spool/cron是/var/spool/cron的软连接,用于存储定时任务文件,但是定时任务文件的命名必须和/etc/passwd中的用户名相匹配
  • /tmp/dnsmasq.d中的.conf文件会作为dnsmasq进程启动时的配置文件加载,而所有对网络的更改都会重启dnsmasq进程

所以可以将一个带有恶意命令的shell脚本上传到/tmp目录下,再将可以 指定dhcp-script路径为刚刚上传的shell脚本 以及 启动tftp服务(通过tftp传输文件来重启dnsmasq进程触发shell脚本执行) 的配置文件上传到/tmp/dnsmasq.d目录下作为dnsmasq进程的配置文件,然后通过tftp传输文件重启dnsmasq进程,运行shell脚本造成远程任意命令执行

(由于dnsmasq开启的tftp服务只有读文件的权限,故不能直接上传恶意文件到路由器文件系统中)

3.本地提权

Linux内核学习笔记: uid之ruid,euid,suid

RUID, 用于在系统中标识一个用户是谁,当用户使用用户名和密码成功登录后一个UNIX系统后就唯一确定了他的RUID

EUID, 用于系统决定用户对系统资源的访问权限,通常情况下等于RUID

SUID,用于对外权限的开放。跟RUID及EUID是用一个用户绑定不同,它是跟文件而不是跟用户绑定

对应文件存取标志的s位就是通常说的SUID位,另外可以看到所有用户都有执行的这个程序权力。当steve用户执行passwd命令的时候。Shell会fork出一个子进程,此时进程的EUID还是steve,然后exec程序/usr/bin/passwd。exec会根据/usr/bin/passwd的SUID位会把进程的EUID设成root, 此时这个进程都获得了root权限, 得到了读写/etc/shadow文件的权限, 从而steve用户可完成密码的修改。 exec退出后会恢复steve用户的EUID为steve.这样就不会使steve用户一直拥有root权限

我的理解是有suid的root用户文件可以被其他用户执行

而在解压上传的备份文件的时候,解压出来的文件会保留其在攻击者自己机器上的uid和完整的文件属性,可以通过suid来进行提权

有几点需要注意

  1. /tmp目录下的文件有着nosuid属性的,所以需要把文件上传到其他目录中(比如上文提到的/tmp/spool/cron目录是/var/spool/cron目录的软连接)

  2. 在一些版本的shell环境上,对于shell脚本的suid不会起作用,所以可以用更加稳妥的binary文件

  3. 为了限制文件大小,可以通过pwntools的asm编译汇编代码生成比较小的binary文件

造成本地权限提升

(这个漏洞产生的原因是 在路由器的lua中使用tar对压缩包进行解压,由于使用的是root权限,所以会保留解压后文件的uid和完整的文件属性)

总结

三个漏洞在没有对任何文件进行逆向的情况下完成了一整套利用过程

在漏洞挖掘的过程中要开拓脑洞,绕过开发者的各种限制,思考各种异常情况下程序可能的行为