IOT漏洞复现----PSV-2020-0437
一.前言
最近在利用之前开发过的模糊测试工具对于各大路由器厂商的固件进行测试,并且进行漏洞挖掘,因此为了方便进一步对于获得的漏洞进行利用,学习了一些之前公开的漏洞复现原理,再次进行复现,本篇文章参考了PSV-2020-0437:Buffer-Overflow-on-Some-Netgear-Routers这篇文章, 对于复现中的一些细节进行详细解释,之后可能也会针对不同厂商的路由器漏洞进行复现。
二.固件获取
对于该漏洞需要获取R6400v2-1.0.4.102的固件,通过下载并且进行binwalk解压就可以获得对应的文件系统,这里就不过多赘述了。
三.固件模拟
对于该固件进行仿真模拟,首先想到的就是利用FirmAE进行模拟,但是通过实现发现,可能由于缺少配置信息等问题,FirmAE并不能直接自动化的进行模拟。因此根据对应漏洞介绍可以知道,该漏洞存在于upnpd二进制文件中,路径为/usr/sbin/upnpd中,因此我们可以利用qemu单独对于该二进制文件进行模拟。
在上述提到的参考文章中,利用了qemu binfmt直接对于upnpd文件进行运行,对应qemu会根据他的架构来进行仿真模拟,虽然确实十分简单,但是在之后进行debug来找偏移等步骤时,会没办法来进行调试,直接调试的话会调试的是qemu而不是对应的upnpd文件,因此本文再次选用利用系统模拟的方式来进行执行。该文件为arm架构,因此我们利用armhf的系统内核来进行模拟,具体命令如下:
1
2
3
4
5
6
7
8
|
sudo 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" \
-net nic,macaddr=00:16:3e:00:00:01 \
-net tap,ifname=tap0,script=no,downscript=no \
-nographic
|
此外对应的文件内容可以在这个链接中进行下载。通过对于文件系统进行模拟之后,便是讲整个解压出来的文件系统利用scp命令拷贝到该系统的目录下,具体命令为:
1 |
sudo scp -r squashfs-root/ root@192.168.1.143: /root/netgear-R6400v2-102
|
这里需要注意的是,对于刚仿真好的内核是没有对应ip的,需要手动进行分配,我这里是通过下面这条指令来分配ip的。
1 |
ifconfig eth0 192.168 . 1.143 / 24 up
|
之后传输结束之后便是解决一些老生常谈的话题,首先就是对于nvram显示没有该设备,因此我们利用Shared Library to intercept nvram这个项目来进行hook,此外由于找不到dlsym,因此我们在LD_PRELOAD时要加上/lib/libdl.so.0,但是在执行过程中说缺少libc.so.6,这里我们只需要把libc.so.0复制并且修改为libc.so.6即可完成。此外对于缺少的信息,也是创建tmp/nvram.ini文件,内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
upnpd_debug_level = 9
lan_ipaddr = 127.0 . 0.1
hwver = R6400
friendly_name = R6400
upnp_enable = 1
upnp_turn_on = 1
upnp_advert_period = 30
upnp_advert_ttl = 4
upnp_portmap_entry = 1
upnp_duration = 3600
upnp_DHCPServerConfigurable = 1
wps_is_upnp = 0
upnp_sa_uuid = 00000000000000000000
lan_hwaddr = AA:BB:CC:DD:EE:FF
|
最后就是利用mount把本地的/proc文件夹和/dev文件加挂在到本地,具体命令如下:
1
2
|
mount - t proc / proc . / squashfs - root / proc
mount - o bind / dev . / squashfs - root / dev
|
自此就完成了对于环境的所有配置工作,之后就是进入到对应文件夹下,执行chroot . sh来设置根目录,这样就仿真完整个环境,执行LD_PRELOAD="/custom_nvram.so /lib/libdl.so.0" ./usr/sbin/upnpd命令就可以完成对应服务的开启,需要注意的是,运行该设备需要开启5000端口和1900端口,通过lsof -i :5000就可以找到对应的进程id,所以在运行之前需要防止其他进行对该端口占用。
四.漏洞原理
该漏洞原理如下,在recvfrom函数中会向inputbuf中输入0x1ffff大小的内容,并且根据upnp_turn_on的参数也就是之前配置的nvram_ini中的值来判断,如果是1并且strlen的长度小于0x100就可以进入到ssdp_http_method_check函数中,这里需要注意的是,如果在recvfrom的内容中,最前面放入\x00进行截断,那么也可以绕过对应长度的检测。

之后进入到ssdp_http_method_check函数之后会进行判断,利用strncpy将inputbuf复制到v39中,之后进入到sub_B9EC

这里进入sub_B9EC中会对于字符串进行赋值,通过刚才所说的可以知道如果我们在发送的数据中,第一个字节为\x00,那么进入到sub_B9EC之后输出的v7的值为0,并且进入下面的判断,会输出Http message error。

最后就是到达了漏洞触发的位置也就是sub_22D20函数中,具体代码如下,这里首先是提取了MX:后面的内容,并且利用strncpy进行复制,但是这里并没有判断复制长度的大小,因此可以再次构造出栈溢出来执行命令执行。

综上对于漏洞触发的原理已经讲解完毕,这里利用上述参考文章中的图进行讲解exp原理,首先第一次我们发送payload,这里需要计算好距离sub_22D20之后偏移的距离,并且写上需要的rop链,之后第二次进行攻击的时候,便是覆盖sub_22D20的返回地址,并且执行栈迁移,最终将pc寄存器指向rop链上。
[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!