复现环境

模拟

首先通过readelf -h busybox 查看固件的架构和型号

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 01 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       1
  Type:                              EXEC (Executable file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x404cf0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x70001005, noreorder, cpic, o32, mips32r2
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0

看到是mips32r2 r3000 的架构小端序。这里有很多的模拟方式可做选择,包括firmaefirmaydne等等工具,但是这一个固件需要执行lwx指令,要求制定cpu架构,所以选择qemu加上自编译的内核进行模拟。

使用buildroot进行编译内核。将defconfig文件复制到根目录,通过 make menuconfig 进入编译界面。如图进行修改

最后make

在output/images文件夹下获得vmlinux 和 rootfs.ext2

使用qemu运行

qemu-system-mipsel -cpu 34Kf -kernel vmlinux -hda rootfs.ext2 -append "root=/dev/sda console=ttyS0" -no-reboot -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

或者

qemu-system-mipsel -cpu 74Kf -kernel vmlinux -hda rootfs.ext2 -append "root=/dev/sda console=ttyS0" -no-reboot -net nic -net tap,ifname=tap0,script=no,downscript=no -nographic

进入后切换目录

mount -o bind /dev ./squashfs-root/dev/
mount -t proc /proc/ ./squashfs-root/proc/
chroot squashfs-root sh

设置网络

ifconfig eth0 ip

至此环境完成

漏洞分析及利用

根据漏洞报告直接找 cstecgi.cgi 进行分析

代码逻辑很清楚

每一个if代表一个行为

剩下的if不再粘贴。需要注意的是这一文件存在json的处理,也就是POST部分的处理

这里获取了topicurl的值进行了后面的字符匹配,根据报告我们去找del的判断,也就是我们漏洞点存在的地方

代码逻辑很简单,字符匹配成功就跳转到对应的地址

但是这里存在一个和漏洞报告不符的地方,就是这里的匹配并不从首个地址开始,而是从v48+16的地址开始的,所以原报告并不能实现。

但是这一漏洞的逻辑确实存在,所以尝试寻找其他能够触发的地方

首先在del的部分进行查找,但是发现都没有。地址布局如下图

代码逻辑如下

我们的输入最多作为数字传入命令执行代码,所以不存在利用方法,因此扩大搜索范围。

最终找到disconnectVPN,进入该行为的处理函数

很简单,就是websgetvar接收pid传参,然后放到sprintf函数到v3 最后直接一个system执行,所以我们构造

curl http://10.10.10.4:8080/cgi-bin/cstecgi.cgi -X POST -d "{\"topicurl\": \"disconnectVPN\",\"pid\":\";ls;\"}"

就可以实现命令执行,效果如图