第一次自主漏洞挖掘,这里写一篇博客特此记录一下
漏洞信息
漏洞文件:/bin/boa
漏洞函数:start_wps()
函数地址:0x45aa28

该函数的调用方式不太一样

HTTP请求->获取pin参数->start_wps()->sprintf拼接系统命令->system执行
在函数中,程序首先通过:v2 = *(_DWORD *)(a1 + 268)获取 HTTP 请求中的用户输入参数。
然后通过:v3 = strstr(v2,”pin=”);查找用户提交的 PIN 参数。
当参数存在时:wscd = (const char *)(v3 + 4);获取用户可控内容。
之后程序直接执行:sprintf(failed,”iwpriv wlan0 set_mib pin=%s”,wscd);
将用户输入拼接到系统命令中,最后:system(failed)执行该命令。
由于用户输入未经过任何过滤,可以通过插入 Shell 特殊字符控制最终执行命令。
环境模拟
解包之后首先尝试运行
看文件架构

拷贝合适的调试工具
cp $(which qemu-mips-static ) .
运行boa文件发现初始化错误
直接去ida查找报错字符Initialize AP MIB failed!

所以这里需要apmib_init返回true才能让函数继续执行
apmib_init()不在 boa 主程序里面,它来自外部动态库(.so)
去找它的函数主体,在/lib/apmib.so文件中
用ida打开

分析可知apmib_init()的作用:
初始化路由器配置数据库(MIB),从Flash读取硬件配置、软件配置、用户配置,然后建立内存中的配置结构,供 boa 后面的 Web 页面调用。
所以可以直接修改apmib_init函数执行函数,让它直接返回1
创建apmib.c文件定义函数apmib_init()
1 | #include<stdio.h> |
然后用gcc-mips-linux-gnu生成 MIPS 架构的 Linux 操作系统可执行文件
mips-linux-gnu-gcc ./apmib.c -o apmib-ld.so -fPIC -shared
之后重新运行
1 | sudo chroot ./ \ |

qemu: uncaught target signal 11 (Segmentation fault) - core dumped
ida调试去寻找报错位置
1 | sudo chroot ./ \ |
配置一下ida的远端调试信息
hostname设置为虚拟机的ip,port为你起的那个端口

在apmib_get的跳转报错了

真正触发程序崩溃的是 0x43B1A4 处的指令
查看 apmib.so 中apmib_get()函数的汇编代码
int __fastcall apmib_get(int n500, unsigned __int8 *p_boot_ver)
这个函数实际上是从路由器的配置数据库(MIB)里,根据编号 n500,把对应配置值读取出来,复制到调用者提供的缓冲区 p_boot_ver
apmib_get(配置项编号, 存放结果的地址)
分析调用的实际情况知道每个pid对应的是什么
所以修改函数apmib_init()
1 | #include <stdio.h> |
然后用gcc-mips-linux-gnu生成 MIPS 架构的 Linux 操作系统可执行文件
mips-linux-gnu-gcc ./apmib.c -o apmib-ld.so -fPIC -shared
然后就可以运行了
sudo chroot ./ ./qemu-mips-static -E LD_PRELOAD="/apmib-ld.so" ./bin/boa

但是跳转的页面是错的
需要改动 web 目录下的 first.asp 文件
将代码 self.location.href=”Basic/Wizard_Easy_LangSelect.asp”;注释掉,
然后将self.location.href=”Basic/Wizard_Easy_Welcome.asp”;复制到else 代码块
即

之后就可以成功访问
接着对start_wps函数进行详细分析

要想执行到system命令注入入口
程序会对var/run/wscd-wlan0.pid和/var/tmp/wscd_status两个文件进行校验,要先创建出这两个文件
1 | mkdir -p var/run |
并且传入参数中要以”pin=····“的形式传入
且apmib_get(59, &n3); 会获取wps配置,要继续修改apmib_get的函数伪造多一种判断情况
#define MIB_WPS_MODE 0x3B
1 | #include <stdio.h> |
之后就可以尝试运行了
模拟攻击
还是起服务但是可以在gdb中调试
1 | sudo chroot ./ ./qemu-mips-static \ |
另开一个窗口来调试
1 | gdb-multiarch ./bin/boa |
在进入system函数之前下断点,方便观察system函数的参数
1 | b *0x45ab80 |

之后按c让它继续运行,期间他会停住等待输入
开另一个窗口发送参数(这里以echo>/var/run/cnvd_test为例去测试执行)
1 | curl --path-as-is \ |
回到gdb调试窗口看参数

看到我们伪造的命令已注入,C让它执行命令

命令注入漏洞实现