CVE-2024-41592 of DrayTek vigor3910 复现

CVE-2024-41592 of DrayTek vigor3910 复现

漏洞简介

	DrayTek Vigor3910 devices through 4.3.2.6 have a stack-based overflow when processing query string parameters because GetCGI mishandles extraneous ampersand characters and long key-value pairs. 

CVE-2024-41592是DrayTek v3910_4.3.2.6版本中发现的一个堆栈溢出漏洞,漏洞点位于sohod64.bin的

getCGI() 函数中, 在该函数中处理字符串参数会造成越界导致栈溢出,精心构造报文可导致rce。

软件版本

工具(虚拟机) 版本号 说明
Ubuntu 18.04
qemu-system-aarch64 2.12.1 DrayTek v3910 GPL源码编译
qemu-aarch64-static 2.11.1 (Debian 1:2.11+dfsg-1ubuntu7.42)
binwalk v2.3.3

环境搭建

Vigor3910的架构为linux+qemu+rtos。

固件分析

固件下载Index of /Vigor3910/Firmware

下载到的固件为v3910_431.all,这是一个加密固件,直接用binwalk分析看不到有效信息,查看熵值为1。

可以尝试从旧版本未加密固件中寻找解密程序进行解密,比如v3910_3972。

image-20250210101106397

                    图1

binwalk 分析固件信息如下,可以看出是未加密的。

image-20250210102103008

                    图2

binwalk -Me v3972/v3910_3972.all无法直接提取文件系统。

image-20250210102317662

                    图3

分析binwalk给出的固件信息。

➜  v3972 binwalk  ./v3910_3972.all

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
273054        0x42A9E         Unix path: /home/eason_jhan/1000b/cavium/firmware/bdk/libbdk-os/bdk-rlock.c
280056        0x445F8         AES S-Box
280568        0x447F8         AES Inverse S-Box
283704        0x45438         SHA256 hash constants, little endian
469662        0x72A9E         Unix path: /home/eason_jhan/1000b/cavium/firmware/bdk/libbdk-os/bdk-rlock.c
476664        0x745F8         AES S-Box
477176        0x747F8         AES Inverse S-Box
480312        0x75438         SHA256 hash constants, little endian
571444        0x8B834         AES Inverse S-Box
571700        0x8B934         AES S-Box
573012        0x8BE54         SHA256 hash constants, little endian
833588        0xCB834         AES Inverse S-Box
833844        0xCB934         AES S-Box
835156        0xCBE54         SHA256 hash constants, little endian
2032941       0x1F052D        Neighborly text, "neighbor %d too different %d from average %d, picking %d.LMC%d.R%d: MAJORTY: Byte %d: picking majority of %d over average %d."
2057224       0x1F6408        AES S-Box
2057736       0x1F6608        AES Inverse S-Box
2079947       0x1FBCCB        Unix path: /home/eason_jhan/1000b/cavium/firmware/bdk/libbdk-os/bdk-rlock.c
2096368       0x1FFCF0        SHA256 hash constants, little endian
2119768       0x205858        LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 2285442 bytes
2886232       0x2C0A58        LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 311880 bytes
3000920       0x2DCA58        LZMA compressed data, properties: 0x5D, dictionary size: 65536 bytes, uncompressed size: 630943 bytes
3155032       0x302458        Flattened device tree, size: 5542 bytes, version: 17
3160664       0x303A58        Flattened device tree, size: 4223 bytes, version: 17
3165272       0x304C58        Flattened device tree, size: 157 bytes, version: 17
3165784       0x304E58        Flattened device tree, size: 6321 bytes, version: 17
3172440       0x306858        Flattened device tree, size: 7806 bytes, version: 17
3180632       0x308858        Flattened device tree, size: 4081 bytes, version: 17
3184728       0x309858        Flattened device tree, size: 555 bytes, version: 17
3185752       0x309C58        Flattened device tree, size: 5957 bytes, version: 17
3191896       0x30B458        Flattened device tree, size: 157 bytes, version: 17
3192408       0x30B658        Flattened device tree, size: 6941 bytes, version: 17
3199576       0x30D258        Flattened device tree, size: 3577 bytes, version: 17
3203160       0x30E058        Flattened device tree, size: 4040 bytes, version: 17
3207256       0x30F058        Flattened device tree, size: 6840 bytes, version: 17
3214424       0x310C58        Flattened device tree, size: 4633 bytes, version: 17
3219544       0x312058        Flattened device tree, size: 8926 bytes, version: 17
3228760       0x314458        Flattened device tree, size: 4170 bytes, version: 17
3233368       0x315658        Flattened device tree, size: 5243 bytes, version: 17
3239000       0x316C58        Flattened device tree, size: 3618 bytes, version: 17
3243096       0x317C58        Flattened device tree, size: 157 bytes, version: 17
3243608       0x317E58        Flattened device tree, size: 3825 bytes, version: 17
3247704       0x318E58        Flattened device tree, size: 5242 bytes, version: 17
3253336       0x31A458        Flattened device tree, size: 3878 bytes, version: 17
3257432       0x31B458        Flattened device tree, size: 674 bytes, version: 17
3258456       0x31B858        Flattened device tree, size: 6157 bytes, version: 17
3265112       0x31D258        Flattened device tree, size: 6854 bytes, version: 17
3272280       0x31EE58        Flattened device tree, size: 3863 bytes, version: 17
3276376       0x31FE58        Flattened device tree, size: 803 bytes, version: 17
3277400       0x320258        Flattened device tree, size: 6321 bytes, version: 17
3284056       0x321C58        Flattened device tree, size: 3392 bytes, version: 17
3288152       0x322C58        Flattened device tree, size: 6840 bytes, version: 17
3295320       0x324858        Flattened device tree, size: 467 bytes, version: 17
3295832       0x324A58        Flattened device tree, size: 6321 bytes, version: 17
3302488       0x326458        Flattened device tree, size: 3392 bytes, version: 17
3306072       0x327258        Flattened device tree, size: 5910 bytes, version: 17
3330136       0x32D058        Flattened device tree, size: 15674 bytes, version: 17
3346008       0x330E58        Flattened device tree, size: 15674 bytes, version: 17
3361880       0x334C58        Flattened device tree, size: 15674 bytes, version: 17
3377752       0x338A58        Flattened device tree, size: 22635 bytes, version: 17
3400792       0x33E458        Flattened device tree, size: 24081 bytes, version: 17
3425368       0x344458        Flattened device tree, size: 16640 bytes, version: 17
3442264       0x348658        Flattened device tree, size: 21379 bytes, version: 17
3463768       0x34DA58        Flattened device tree, size: 14770 bytes, version: 17
3478616       0x351458        Flattened device tree, size: 15126 bytes, version: 17
3493976       0x355058        Flattened device tree, size: 15786 bytes, version: 17
3509848       0x358E58        Flattened device tree, size: 16204 bytes, version: 17
3526232       0x35CE58        Flattened device tree, size: 14856 bytes, version: 17
3541592       0x360A58        Flattened device tree, size: 15869 bytes, version: 17
3557526       0x364896        Copyright string: "Copyright (C) 2016, Cavium Inc."
3559079       0x364EA7        Copyright string: "copyright notice and this permission notice shall be"
3561562       0x36585A        Unix path: /sys/class/gpio/gpio472) for DSL model
5052256       0x4D1760        CRC32 polynomial table, little endian
5058320       0x4D2F10        AES Inverse S-Box
5065888       0x4D4CA0        AES S-Box
5099137       0x4DCE81        Motorola S-Record; binary data in text format, record type: header
5259312       0x504030        Linux kernel ARM64 image, load offset: 0x80000, image size: 44011520 bytes, little endian, 4k page size,
5499456       0x53EA40        SHA256 hash constants, little endian
12693552      0xC1B030        ELF, 64-bit LSB shared object, version 1 (SYSV)
12741544      0xC26BA8        gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)
12820184      0xC39ED8        Intel x86 or x64 microcode, sig 0xffffff80, pf_mask 0x00, 1DE0-08-26, size 2048
12820328      0xC39F68        Intel x86 or x64 microcode, sig 0xffffff80, pf_mask 0x00, 1DE0-08-26, size 2048
12897440      0xC4CCA0        DES SP2, little endian
12897952      0xC4CEA0        DES SP1, little endian
12923200      0xC53140        LZO compressed data
12925744      0xC53B30        CRC32 polynomial table, little endian
13188944      0xC93F50        Copyright string: "Copyright (c) 1999-2006 Intel Corporation."
13196536      0xC95CF8        Copyright string: "Copyright (c) 2009 - 2012 Intel Corporation."
13197320      0xC96008        Copyright string: "Copyright (c) 1999-2008 Intel Corporation."
13199736      0xC96978        Copyright string: "Copyright (c) 2013 - 2016 Intel Corporation."
13410380      0xCCA04C        Certificate in DER format (x509 v3), header length: 4, sequence length: 14848
14404968      0xDBCD68        Unix path: /dev/vc/0
14479296      0xDCEFC0        Ubiquiti partition header, header size: 56 bytes, name: "PARTNAME=%s", base address: 0x74790A00, data size: 23295090 bytes
14486472      0xDD0BC8        xz compressed data
14569424      0xDE4FD0        Unix path: /lib/firmware/updates/4.9.0-OCTEONTX_SDK_6_2_0_p3_build_38
14663912      0xDFC0E8        Ubiquiti firmware additional data, name: UTE DEVICE DIAGNOSTIC, size: 1145372672 bytes, size2: 0 bytes, CRC32: 0
14712280      0xE07DD8        Copyright string: "Copyright(c) 1999-2006 Intel Corporation"
14789199      0xE1AA4F        Copyright string: "Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>"
14812265      0xE20469        Copyright string: "Copyright(c) Pierre Ossman"
14848048      0xE29030        Unix path: /sys/firmware/devicetree/base
14848848      0xE29350        Unix path: /sys/firmware/fdt': CRC check failed
14864129      0xE2CF01        Neighborly text, "neighbor table overflow!ate is %x"
15613000      0xEE3C48        LZ4 compressed data, legacy
15613426      0xEE3DF2        Executable script, shebang: "/bin/sh"
16971299      0x102F623       Unix path: /dev/net/tun.
17236166      0x10700C6       mcrypt 2.5 encrypted data, algorithm: "w", keysize: 332 bytes, mode: """,
19705376      0x12CAE20       XML document, version: "1.0"
20045201      0x131DD91       VMware4 disk image
20045848      0x131E018       Executable script, shebang: "/bin/sh"
20089785      0x1328BB9       AES Inverse S-Box
20090041      0x1328CB9       AES S-Box
20090329      0x1328DD9       DES PC1 table
20090417      0x1328E31       DES PC2 table
20111190      0x132DF56       Base64 standard index table
21756040      0x14BF888       Unix path: /sys/class/net/%s/phy80211
22373111      0x15562F7       Base64 standard index table
22816893      0x15C287D       MPEG transport stream data
23678637      0x1694EAD       Copyright string: "Copyright 1995-2005 Jean-loup Gailly "
23745388      0x16A536C       PGP RSA encrypted session key - keyid: D8020270 1B1148DC RSA Encrypt-Only 1024b
24029059      0x16EA783       Unix path: /dev/net/tun
24056482      0x16F12A2       AES S-Box
24057270      0x16F15B6       AES Inverse S-Box
24533651      0x1765A93       eCos RTOS string reference: "ecosW"
24543379      0x1768093       HTML document header
24563221      0x176CE15       LUKS_MAGIC
24564177      0x176D1D1       xz compressed data
24873394      0x17B89B2       OpenSSL encryption, salted, salt: 0xC00770252D323573
24884301      0x17BB44D       HTML document header
24906969      0x17C0CD9       Private key in DER format (PKCS header length: 4, sequence length: 2345
25343574      0x182B656       Unix path: /usr/local/shk
25480049      0x184CB71       Executable script, shebang: "/bin/bash"
26449086      0x19394BE       SHA256 hash constants, little endian
26965826      0x19B7742       Cisco IOS microcode, for ""
27792979      0x1A81653       gzip compressed data, maximum compression, has header CRC, last modified: 1974-10-07 02:33:45 (bogus date)
30516402      0x1D1A4B2       HTML document header
30707709      0x1D48FFD       Base64 standard index table
32138317      0x1EA644D       HTML document header
32463276      0x1EF59AC       PNG image, 32 x 24, 8-bit/color RGBA, interlaced
32463352      0x1EF59F8       Zlib compressed data, default compression
32492091      0x1EFCA3B       GIF image data, version "89a", 5 x
32548082      0x1F0A4F2       JPEG image data, EXIF standard
32574798      0x1F10D4E       Zlib compressed data, best compression
32577456      0x1F117B0       Zlib compressed data, best compression
32580729      0x1F12479       JPEG image data, JFIF standard 1.02, thumbnail 11x98
32751022      0x1F3BDAE       Zlib compressed data, best compression
32760485      0x1F3E2A5       Zlib compressed data, default compression
32767499      0x1F3FE0B       JPEG image data, JFIF standard 1.02
32822738      0x1F4D5D2       Zlib compressed data, best compression
32831773      0x1F4F91D       XML document, version: "1.0"
32866201      0x1F57F99       JPEG image data, JFIF standard 1.02
32905743      0x1F61A0F       GIF image data, version "89a", 30 x 30
32943989      0x1F6AF75       Zlib compressed data, best compression
32947100      0x1F6BB9C       Zlib compressed data, best compression
32954824      0x1F6D9C8       XML document, version: "1.0"
32972713      0x1F71FA9       JPEG image data, JFIF standard 1.01
33011108      0x1F7B5A4       PNG image, 52 x 5, 8-bit/color RGBA, non-interlaced
33201563      0x1FA9D9B       XML document, version: "1.0"
33236782      0x1FB272E       PNG image, 1000 x 280, 8-bit/color RGBA, interlaced
33318819      0x1FC67A3       Zlib compressed data, best compression
33382838      0x1FD61B6       JPEG image data, JFIF standard 1.01
33382868      0x1FD61D4       TIFF image data, little-endian offset of first image directory: 8
33516114      0x1FF6A52       ZBOOT firmware header, header size: 32 bytes, load address: 0x9C54505A, start address: 0x8B844857, checksum: 0x4F8B885F, version: 0xFF979388, image size: 991901497 bytes
33609975      0x200D8F7       PNG image, 300 x 84, 8-bit/color RGBA, non-interlaced
33776158      0x203621E       XML document, version: "1.0"
33809104      0x203E2D0       PNG image, 310 x 531, 8-bit/color RGBA, non-interlaced
33809203      0x203E333       Zlib compressed data, best compression
34312241      0x20B9031       JPEG image data, JFIF standard 1.01
34352652      0x20C2E0C       TIFF image data, big-endian, offset of first image directory: 8
34799229      0x212FE7D       Base64 standard index table
35201331      0x2192133       AES S-Box
35201587      0x2192233       AES Inverse S-Box
35282151      0x21A5CE7       HTML document header
35375557      0x21BC9C5       Base64 standard index table
38441243      0x24A911B       Certificate in DER format (x509 v3), header length: 4, sequence length: 873
38694241      0x24E6D61       Executable script, shebang: "/bin/bash"
38694568      0x24E6EA8       Unix path: /dev/net/tun
39750489      0x25E8B59       Unix path: /usr/lib64/tc/
39881890      0x2608CA2       Copyright string: "Copyright (C) 2004 by Harald Welte <laforge@gnumonks.org>"
40546844      0x26AB21C       Unix path: /home/ruby/X
40667261      0x26C887D       Copyright string: "Copyright (C) 2018, Thomas G. Lane, Guido Vollbeding"
40692035      0x26CE943       Unix path: /home/ruby/X
42108450      0x2828622       Copyright string: "Copyright (C) 2018, Thomas G. Lane, Guido Vollbeding"
42240067      0x2848843       Copyright string: "Copyright (C) 2018, Thomas G. Lane, Guido Vollbeding"
42600735      0x28A091F       gzip compressed data, ASCII, from VM/CMS, last modified: 1995-08-24 06:41:07
42608185      0x28A2639       ELF, 64-bit LSB processor-specific,
42845890      0x28DC6C2       Neighborly text, "neighbor C %s"
43871781      0x29D6E25       Unix path: /home/ruby/X
44237701      0x2A30385       Executable script, shebang: "/bin/sh"
44249877      0x2A33315       OpenSSH RSA public key
45239782      0x2B24DE6       SHA256 hash constants, little endian
45601353      0x2B7D249       gzip compressed data, ASCII, from VM/CMS, last modified: 2008-04-20 10:46:28
47200461      0x2D038CD       SHA256 hash constants, little endian
47222790      0x2D09006       AES Inverse S-Box

固件基本结构通常包含bootloader、kernel、rootfs等等,在binwalk给出的固件信息中他们具有一些可识别的特征。

bootloader通常位于固件开头,存在bdk,加密算法如AES、SHA等字样。

kernel通常以压缩数据开头,存在ftb设备树标识,kernel header。

rootfs通常以压缩数据开头,存在Executable script,图片、html标识,压缩数据。

根据这些判断0- 2119767为bootloader,2119768-15613425为kernel,15613426-末尾为rootfs。

旧固件提取

使用dd命令提取rootfs。

➜  v3972 dd if=v3910_3972.all of=fs.lz4 bs=1 skip=15613000 count=$((48978480-15613000))
33365480+0 records in
33365480+0 records out
33365480 bytes (33 MB, 32 MiB) copied, 80.5077 s, 414 kB/s

安转lz4解压缩。

sudo apt-get install liblz4-tool

➜  v3972 file fs.lz4 
fs.lz4: LZ4 compressed data (v0.1-v0.9)

➜  v3972 lz4 -d fs.lz4 
Decoding file fs 
Error 53 : Decoding Failed ! Corrupted input detected !

虽然有报错,但还是解压出了文件系统fs,file查看到是打包的cpio格式。

➜  v3972 file fs
fs: ASCII cpio archive (SVR4 with no CRC)

用binwalk直接提取的到文件系统。

image-20250210113041097

                    图4

寻找解密程序

解密程序一定与固件的更新和升级相关,尝试在文件系统中搜索update、upgrade、firmware等字符。

➜  cpio-root grep -i -r 'upgrade' -l  ./
./usr/sbin/tcpdump
./usr/bin/qemu-system-aarch64
./sbin/rc
./etc/runcommand/gci_exp
./etc/runcommand/fw_upload
./lib64/libitm.so.1.0.0
./testfunc/misc.sh
./testfunc/auto_cfg_err.sh
./firmware/run.sh
./firmware/vqemu/sohod64.bin
./lib/libspice-server.so.1
./lib/libspice-server.so
./lib/libext2fs.so.2.4
./lib/libspice-server.so.1.13.0
➜  cpio-root grep -i -r 'upgrade'  -l ./ | grep  f             
./etc/runcommand/fw_upload
./testfunc/misc.sh
./testfunc/auto_cfg_err.sh
./firmware/run.sh
./firmware/vqemu/sohod64.bin
./lib/libext2fs.so.2.4

./etc/runcommand/fw_upload是一个shell脚本,其中包含了完整的固件升级流程。

结合ai分析找到如下关键部分,用fw_unpacker对固件进行解包,再chacha20解密。

image-20250210114759720

                    图5

加密固件提取

从shell脚本中大概能看出fw_unpacker所需参数为-i firmware -o ./dir/ -m ?

不知道这个-m是用来做什么的,ida分析一下,程序判断了-i、-o、-m都不能为空,model参数需要和v12相同才能进行正常的解包。

image-20250210121834959

                    图6

fw_unpacker为aarch64架构,用qemu运行一下看看情况。可以看到fw为v3910,也就是说model也必须是v3910。

image-20250210123044483

                    图7

修改model再次尝试,可以看到解包成功,得到如下文件。

image-20250210123150046

                    图8

之后再用chacha20解密,从./etc/runcommand/fw_upload中可以看出其参数如下

chacha20 enc file denc file TMP_FW_OUTPUT_FOLDER/nonce

尝试解密,成功得到一个解密镜像,这个镜像结构就和v3910_3972很相似了。

image-20250210123753327

                    图9

用dd从解密得到的镜像中提取出文件系统部分,lz4解压,binwalk提取就能得到文件系统。

image-20250210124608938

                    图10

image-20250210124805826

                    图11

固件模拟

参考网上文章CVE-2024-41592 vigor 栈溢出漏洞分析,从etc下寻找init相关文件,inittab中执行了/sbin/rc

image-20250210125507439

                    图12

从/sbin/rc中找到一个/firmware/run.sh,提到了run_linux.sh,

image-20250210130508988

                    图13

run_linux.sh中提到了执行fw_setenv purelinux 1和setup_qemu_linux.sh,从中可以看出最终是用qemu启动了./vqemu/sohod64.bin提供服务的。前者是用来设置环境变量。

image-20250210130610424

                    图14

分析后者setup_qemu_linux.sh发现只要用来设置网络。用到了两张网卡,分别是eth0和eth1。先将网卡创建出来。

 sudo ip tuntap add dev eth0 mode tap 
 sudo ip tuntap add dev eth1 mode tap 
 sudo ip link set eth0 up 
 sudo ip link set eth1 up

依次启动setup_qemu_linux.sh和run_linux.sh就可以启动服务了。

但是我在运行时始终卡在这一步,并且似乎还有报错信息。

!! snprintf function can't meet draytek's requirement!

img

                    图15

参考其他文章CVE-2024-41592 vigor 栈溢出漏洞分析得知启动服务的qemu是经过厂商二次开发的,而我用的是本地安转的qemu。需要下载官方提供的GPL源码编译qemu启动服务。

v3910 GPL源码下载 DrayTek File Server

./configure --enable-kvm --enable-debug --target-list=aarch64-softmmu
make

将编译得到的qemu-system-aarch64放到/firmware下再启动服务即可访问到web页面。

image-20250209205144554

                    图16

漏洞分析

ida分析./vqemu/sohod64.bin文件,漏洞产生于getcgi函数中,它几乎在所有cgi函数中均会被调用用来解析请求参数。通过搜索字符串QUERY_STRING的方式对其定位。

首先比较是否是GET请求,接着从请求中提取原始的payload,通过循环为payload中每个键值对分配堆空间,将堆地址写到栈中,如图16所示。

makeword会从payload中以&为分隔符匹配键值对,并为其分配堆内存,将键的堆地址写进栈里(stack_addr + 8 * idx),随后对值进行url解码,将值的堆地址存放在((stack_addr + 8 * idx+4))如图18所示,在这一过程中,并未对idx大小做限制,只要payload数据不为空,就不断循环分配堆地址写到栈中,如果构造大量的&符号,就可以造成堆栈溢出覆盖函数返回地址为堆地址。

image-20250209204234324

                    图17

image-20250209214537160

                    图18

图18来源:forescout.com/resources/draybreak-draytek-research/

直接覆盖返回地址会导致程序崩溃,因为在每个cgi函数return之前,程序都会调用FreeCtrlName(),将之前makeword函数分配的堆地址置0,这个地址是用来存放键值对的键的堆地址,在栈地址低地址处,在高地址的用来存放键值对的值的堆地址却未被置0,如图20所示。

image-20250209222016152

                    图19

image-20250209224021512

                    图20

图20来源:forescout.com/resources/draybreak-draytek-research/

要劫持执行流就必须绕过FreeCtrlName()函数,它的循环条件是栈地址不为空,所以需要找到一个cgi,在执行了get_cgi()之后,能向图4中Query_String_Buffer到Return_Address之间的区域写一个0,来终止FreeCtrlName()的执行。如果要完成未授权rce,则这个cgi还必须是不需要认证就可以执行的。

调试分析

在run_linux.sh的qemu-system-aarh64添加-s参数便于调试,启动服务后,在终端运行如下命令进入调试。(启动服务后不要立即进入调试,这可能会影响服务的初始化,即使顺利进入gdb也难以进行有效调试,尽量等待终端循环显示reboot qemu后再进入调试)

gdb-multiarch --eval-command="set architecture aarch64" --eval-command="target remote localhost:1234" 

进入调试后在get_cgi函数下断点,接着发送请求,然后c过去。

http://192.168.1.1/cgi-bin/wlogin.cgi?&&&

image-20250209230338216

                    图21

如下图所示执行流已经到了getcgi中的makeword()处,继续执行。

image-20250209230625972

                    图22

由于是通过跳转指令进入子函数的,之前在传统的x86架构gdb调试中使用n去单步步过子函数是不生效的,finish命令也达不到想要的功效,可以在子函数的返回地址下个断点再c过去比较快。

如图所示,x7存放的是由makeword()分配给键值对的堆地址,它将被存储在x20中的栈地址0x468412f0处。

image-20250209231212645

                    图23

如图所示,红框1是键值对的键分配的堆地址,他们都存放在8字节栈地址的低地址处,由于请求中只有&符,所以0x468412f0的高4字节地址处为空。aarch64与x86开辟栈帧的方式有所不同,getcgi函数的返回地址在红框1上面也就是栈的低地址处,红框2存放的是调用getcgi的函数funcB(vuln.cgi)的返回地址,以此类推,红框3存放的是调用funcB的函数funcA的返回地址,下图与图18相对应。

image-20250209232126685

                    图24

堆栈溢出只能向栈的高地址处覆盖,所以劫持执行流需要覆盖funcB(vuln.cgi)的返回地址。

漏洞验证

启动仿真环境,正常启动后,程序循环打印reboot qemu。

image-20250209205025994

                    图25

这时已经可以访问到web页面,默认账号密码是admin:admin。

image-20250209205144554

                    图26

找到一个cgi,在请求参数时填入大量&。

http://192.168.1.1/cgi-bin/wlogin.cgi?&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

服务崩溃如下图27所示。

image-20250209215046781

                    图27

总结

解密固件的方法难度比较高,但具有一定的通用性,如果一个固件被加密,那么在旧版本固件中,由于版本更新的需要,通常存在一个解密程序。

这个设备的固件未开启canary保护,是实现rce的关键条件之一。

固件仿真需要深入分析启动相关文件,处理报错,解决报错,难度较高,涉及到网络配置与服务程序启动的部分是至关重要的。

参考文章

forescout.com/resources/draybreak-draytek-research/

DrayTek Vigor3910 CVE-2024-41592分析 | CN-SEC 中文网

CVE-2024-41592 vigor 栈溢出漏洞分析

an article of monologue

posted @ 2025-02-10 14:31  Sta8r9  阅读(819)  评论(0)    收藏  举报