centos下安装firmware-mod-kit
yum install git zlib1g-dev xz-devel python-magic #Prerequisites
git clone https://github.com/mirror/firmware-mod-kit.git
cd firmware-mod-kit/src
./configure && make
解压镜像: ./unsquashfs_all.sh image
,解压出的文件保存在squashfs-root 文件夹中
ll
总用量 20
drwxr-xr-x 2 root root 4096 11月 19 2015 bin
drwxr-xr-x 2 root root 47 11月 19 2015 dev
lrwxrwxrwx 1 root root 8 12月 30 14:47 etc -> /var/etc
drwxr-xr-x 6 root root 4096 11月 19 2015 etc_ro
lrwxrwxrwx 1 root root 9 12月 30 14:47 home -> /var/home
lrwxrwxrwx 1 root root 11 12月 30 14:47 init -> bin/busybox
drwxr-xr-x 3 root root 4096 11月 19 2015 lib
drwxr-xr-x 2 root root 6 11月 19 2015 mnt
drwxr-xr-x 2 root root 6 11月 19 2015 proc
lrwxrwxrwx 1 root root 9 12月 30 14:47 root -> /var/root
drwxr-xr-x 2 root root 4096 11月 19 2015 sbin
drwxr-xr-x 2 root root 6 11月 19 2015 sys
drwxr-xr-x 2 root root 6 11月 19 2015 tmp
drwxr-xr-x 6 root root 64 11月 19 2015 usr
drwxr-xr-x 6 root root 56 11月 19 2015 var
lrwxrwxrwx 1 root root 11 12月 30 14:47 webroot -> var/webroot
drwxr-xr-x 7 root root 4096 11月 19 2015 webroot_ro
漏洞分析
在bin 文件夹中找到存在漏洞的文件 httpd ,使用 checksec 看一下开启的保护:
>>> from pwn import *
>>> print ELF('./httpd')
[*] '/root/sploitfun/iot/firmware-mod-kit/squashfs-root/bin/httpd'
Arch: arm-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8000)
32 位程序,只开启了 NX,丢进 IDA 开始分析,由于是复现漏洞,所以直接定位到函数 R7WebsSecurityHandler,按F5 查看反编译代码(代码比较多,只把关键的地方放上来)
if ( *((_DWORD *)v18 + 46) )
{
v40 = strstr(*((const char **)v18 + 46), "password=");
if ( v40 )
sscanf(v40, "%*[^=]=%[^;];*", &v33);
else
sscanf(*((const char **)v18 + 46), "%*[^=]=%[^;];*", &v33);
}
if ( strlen(&s) <= 3
|| (v42 = strchr(&s, 46)) == 0
|| (v42 = (char *)v42 + 1, memcmp(v42, "gif", 3u))
&& memcmp(v42, "png", 3u)
&& memcmp(v42, "js", 2u)
&& memcmp(v42, "css", 3u)
&& memcmp(v42, "jpg", 3u)
&& memcmp(v42, "jpeg", 3u) )
结合上下文来理解这段代码,第100 行使用了函数 strstr 尝试在 (v18 + 46) 处找到 “password=” 字符串的位置,其中 v18 + 46 是用户的 HTTP 请求,password 是请求中 cookie 的一个字段,如果找到了 password,就会进入接下来的逻辑,调用函数 sscanf,使用正则匹配 “password=” 之后的字符串,并将匹配出的结果存入变量 v33 中,结合 v33 的变量定义
char v33; // [sp+304h] [bp-1C0h]@1
很明显这里是存在栈溢出的,代码没有判断字段的最大长度,直接将内容拷贝到栈上,如果用户精心构造一个password,那么可能有机会控制整个程序的流程,进而达到远程执行代码的目的。
在复现漏洞的时候经常会摸不到头脑,比如凭什么说v18 + 46 代表 http 请求,这个函数究竟想要干什么等等,加上没有真正的路由器,一切只能在 qemu 中模拟,想要真正从根本上理解漏洞的成因是比较困难的,解决办法只能是不断地分析关键函数并且根据程序功能猜测这些究竟是什么,有条件的话可以考虑搞来一台路由器模拟真实的环境,这或许能够解决一部分问题。
搭建调试环境
在从前,想要跨平台模拟运行其他平台的程序是很困难的,幸好一路大佬开发出了QEMU,关于 QEMU 的具体信息可在其官方网站上找到,实际上它就是一个虚拟机,能够虚拟大部分硬件设备,ARM 自然也包括在内,下面是一张关于 QEMU 的简图
---------------------------------------------
|apps |apps |apps |
|--------------|--------------|--------------|
|客户端系统 |客户端系统 |客户端系统 |
|--------------|--------------|--------------|
|QEMU(x86架构) |QEMU(ARM架构) |QEMU(x86架构) |
|--------------------------------------------|
| 宿主系统 |
|--------------------------------------------|
| 硬件平台(x86架构) |
----------------------------------------------
其中Qemu模块可以CPU模拟,内存模拟,I/O设备模拟,其他设备模拟等等
它在宿主机上模拟了相应硬件的环境,并在这些模拟的环境上面运行客户系统,这种机制类似于VMware,无需关机重启,即可在一套硬件上运行多种不同的系统。