记一次Vigor3910路由器敏感溢出分析

IoT 2年前 (2022) admin
1,110 0 0

参考

https://www.zhiwanyuzhou.com/index.php/2022/09/17/%e4%bb%8ecve%e5%88%b0draytek-vigor%e7%b3%bb%e5%88%97%e4%bc%81%e4%b8%9a%e8%b7%af%e7%94%b1%e5%99%a8%e5%9b%ba%e4%bb%b6%e5%88%86%e6%9e%90/Vigor 3910分析与利用.pdf

漏洞信息

https://nvd.nist.gov/vuln/detail/CVE-2022-32548记一次Vigor3910路由器敏感溢出分析Trellix 公司的安全研究员发现一个严重的远程代码执行 (RCE)漏洞 (CVE-2022-32548),影响29款 DrayTek Vigor 系列企业路由器易受攻击的机型如下:

  • Vigor3910

  • Vigor1000B

  • Vigor2962 系列

  • Vigor2927 系列

  • Vigor2927 LTE 系列

  • Vigor2915 系列

  • Vigor2952 / 2952P

  • Vigor3220 系列

  • Vigor2926 系列

  • Vigor2926 LTE 系列

  • Vigor2862 系列

  • Vigor2862 LTE 系列

  • Vigor2620 LTE 系列

  • VigorLTE 200n

  • Vigor2133 系列

  • Vigor2762 系列

  • Vigor167

  • Vigor130

  • VigorNIC 132

  • Vigor165

  • Vigor166

  • Vigor2135 系列

  • Vigor2765 系列

  • Vigor2766 系列

  • Vigor2832

  • Vigor2865 系列

  • Vigor2865 LTE 系列

  • Vigor2866 系列

  • Vigor2866 LTE 系列

固件

https://www.draytek.co.uk/support/downloads/vigor-3910/older-firmware/firmware-4311记一次Vigor3910路由器敏感溢出分析

vigor-3910发行说明:https://www.draytek.co.uk/support/downloads/vigor-3910/older-firmware/firmware-4311/send/1143-4311/2592-readme-v3910-4311

什么是.all文件

记一次Vigor3910路由器敏感溢出分析

固件分析

用010 Editor打开v3910_4311.all

本人的010 Editor经过ida pro破解了

记一次Vigor3910路由器敏感溢出分析

binwalk解包

binwalk -Me v3910_4311.all使用binwalk进行初步分析,发现无法解包;发现enc_image,初步认为该固件是加密的记一次Vigor3910路由器敏感溢出分析

既然固件加密,可查看旧版本固件是否有不加密的固件进行“过度”操作

旧版本固件分析

递归提取文件:binwalk -Me v3910_3972.all记一次Vigor3910路由器敏感溢出分析

$ binwalk -Me v3910_3972.all 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
273054       0x42A9E         Unix path: /home/eason_jhan/1000b/cavium/firmware/bdk/libbdk-os/bdk-rlock.c
283704       0x45438         SHA256 hash constants, little endian
469662       0x72A9E         Unix path: /home/eason_jhan/1000b/cavium/firmware/bdk/libbdk-os/bdk-rlock.c
480312       0x75438         SHA256 hash constants, little endian
573012       0x8BE54         SHA256 hash constants, little endian
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."
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       device tree image (dtb)
3160664       0x303A58       device tree image (dtb)
3165272       0x304C58       device tree image (dtb)
3165784       0x304E58       device tree image (dtb)
3172440       0x306858       device tree image (dtb)
3180632       0x308858       device tree image (dtb)
3184728       0x309858       device tree image (dtb)
3185752       0x309C58       device tree image (dtb)
3191896       0x30B458       device tree image (dtb)
3192408       0x30B658       device tree image (dtb)
3199576       0x30D258       device tree image (dtb)
3203160       0x30E058       device tree image (dtb)
3207256       0x30F058       device tree image (dtb)
3214424       0x310C58       device tree image (dtb)
3219544       0x312058       device tree image (dtb)
3228760       0x314458       device tree image (dtb)
3233368       0x315658       device tree image (dtb)
3239000       0x316C58       device tree image (dtb)
3243096       0x317C58       device tree image (dtb)
3243608       0x317E58       device tree image (dtb)
3247704       0x318E58       device tree image (dtb)
3253336       0x31A458       device tree image (dtb)
3257432       0x31B458       device tree image (dtb)
3258456       0x31B858       device tree image (dtb)
3265112       0x31D258       device tree image (dtb)
3272280       0x31EE58       device tree image (dtb)
3276376       0x31FE58       device tree image (dtb)
3277400       0x320258       device tree image (dtb)
3284056       0x321C58       device tree image (dtb)
3287640       0x322A58       device tree image (dtb)
3288152       0x322C58       device tree image (dtb)
3295320       0x324858       device tree image (dtb)
3295832       0x324A58       device tree image (dtb)
3302488       0x326458       device tree image (dtb)
3306072       0x327258       device tree image (dtb)
3330136       0x32D058       device tree image (dtb)
3346008       0x330E58       device tree image (dtb)
3361880       0x334C58       device tree image (dtb)
3377752       0x338A58       device tree image (dtb)
3400792       0x33E458       device tree image (dtb)
3425368       0x344458       device tree image (dtb)
3442264       0x348658       device tree image (dtb)
3463768       0x34DA58       device tree image (dtb)
3478616       0x351458       device tree image (dtb)
3493976       0x355058       device tree image (dtb)
3509848       0x358E58       device tree image (dtb)
3526232       0x35CE58       device tree image (dtb)
3541592       0x360A58       device tree image (dtb)
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
5099137       0x4DCE81       Motorola S-Record; binary data in text format, record type: header
5259312       0x504030       Microsoft executable, portable (PE)
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
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
14712280     0xE07DD8       Copyright string: "Copyright(c) 1999-2006 Intel Corporation"
14789199     0xE1AA4F       Copyright string: "Copyright 2005-2007 Rodolfo Giometti <[email protected]>"
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"
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 "
24029059     0x16EA783       Unix path: /dev/net/tun
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
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 <[email protected]>"
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

记一次Vigor3910路由器敏感溢出分析通过binwalk的分析结果可以知道,这个固件应该不是加密固件,但是binwalk并不支持它的解包操作,如此我们先大概回顾一下固件的基本结构:记一次Vigor3910路由器敏感溢出分析通过以上固件的基本结构,结合binwalk的信息,我们可以这样假设:

偏移 功能 备注
0-0x205857 BootLoader 先大概确定内核,再往上推演
0x205858-0xEE3DF1 Kernel 因为有LZMA的标识,可以大概推断为内核,并且这区间有dtb设备树、PE结构等标识
0xEE3DF2-末尾 Rootfs 从这里开始有Executable script的标识,表示存在实际的shell脚本文件内容了,以及后面有图片、网页的标识,可以断定为文件系统

截取0xEE3DF2的部分内容,可以看出此的确为shell脚本的内容,但是脚本里面充斥着很多非ASCII的内容,经过经验分析,此脚本可能被压缩了。记一次Vigor3910路由器敏感溢出分析再来分析binwalk的解包结果,在0xC26BA8处有个gzip的标识,经过解压缩,可以知道其为内核的配置信息:记一次Vigor3910路由器敏感溢出分析记一次Vigor3910路由器敏感溢出分析知道内核决定了支持的文件系统的类型,那么其配置信息内部可能会定义文件系统的相关配置,如此我们搜索rootfs关键字,最终找到了initramfs.cpio.lz4的字样:记一次Vigor3910路由器敏感溢出分析后缀名lz4,可以联想到假定的rootfs区段内shell脚本之前有个LZ4压缩数据,那么可以断定从0xEE3C48应该为文件系统的起始位置。

15613000      0xEE3C48        LZ4 compressed data, legacy
15613426     0xEE3DF2       Executable script, shebang: "/bin/sh"

现在知道了,binwalk可能对lz4压缩不太支持,那么我们手动对binwalk进行功能添加:

# Ubuntu系统 添加lz4压缩工具
apt install liblz4-tool
# 加入lz4的压缩支持(binwalk安装路径/proc/thread-self/cwd/tools/binwalk-2.3.3/src/binwalk/config/extract.conf,如果找不到用find命令查找)
^lz4 compressed data:lz4:lz4 -d '%e' '%e.bin'

记一次Vigor3910路由器敏感溢出分析使用binwalk -Me解包固件,获取文件系统记一次Vigor3910路由器敏感溢出分析

新版本固件分析

旧版固件是未加密的,新版固件是加密的,那么未加密->加密的过程会有个“过渡”操作,通过关键字“firmware”对整个文件系统进行查找,最终找到一个文件fw_upload里面有对旧版和新版固件的操作:记一次Vigor3910路由器敏感溢出分析通过分析可知固件的结构:

序号 偏移 功能
1 0x0-0x03 标识,字符串6216
2 0x04-0x07 填充,值0
3 0x08-0x0B header的checksum校验值,值0x3EFB072A
4 0x0C 值1
5 0x0D-0x3F 固件版本号,字符串4.3.2_RC5a
6 0x40-0x43 长度,值0x5
7 0x44-0x48 型号,字符串v3910
8 0x49-0x4C 填充1,值0
9 0x4D-0x50 未知,值0x00000059
10 0x51-0x54 nonce内容的checksum校验值,值0x6B075354
11 0x55-0x88 填充2,值0
12 0x89-0x8C 字符串nonce的长度,值0x5
13 0x8D-0x92 字符串nonce
14 0x93-0x95 nonce内容的长度,值0xC
15 0x96-0xA1 nonce内容,字符串xRDYwRMx0B7u
16 0xA2-0xA5 填充1,值0
17 0xA6-0xA9 未知,值0x02FD1A51
18 0xAA-0xAD enc_Image内容的checksum校验值,值0x26B0401D
19 0xAE-0xE1 填充2,值0
20 0xE2-0xE5 字符串enc_Image的长度,值0x9
21 0xE6-0xEE 字符串enc_Image
22 0xEF-0xF2 enc_Image内容的长度,值0x02FD1A00
23 0xF3-0x2FD1AF2 enc_Image内容
以下内容以此类推,包含以下区块:
enc_thunder-bootfs-uboot-t81.img

fw_release

fw_ver

pid

oid

uver

bdk_ver

linux_ver

drayqemu_ver

fw_release

fw_ver

pid

oid

uver

bdk_ver

fw_release

fw_ver

pid

oid

uver

bdk_ver

每个区块间隔0x40字节,即填充1到填充2之间的内容。checksum校验算法:

def checksum(data, num):
  length = len(data)
  num = (~num) & 0xFFFFFFFF
   if not num:
      num = 0xFFFFFFFF
  tmp1 = 0
   for i in range(length):
      tmp1 = data[i]
       for j in range(8):
          tmp2 = tmp1 ^ num
          num >>= 1
           if (tmp2 & 1):
              num ^= 0xEDB88320
          tmp1 >>= 1
  return (~num) & 0xFFFFFFFF

需要关心的就是enc_Image区段,它是chacha20加密的,那么找到key,nonce就能解密了

解密

采用了chacha20算法加密了固件,需要两个值进行解密,一个是secret、一个是nonce记一次Vigor3910路由器敏感溢出分析记一次Vigor3910路由器敏感溢出分析nonce为10 78 DE AA 0D 6A F8 F5 A6 DE EF 98,其次也发现了enc_image,从0xF3开始进⾏解密,接下去就是需要寻找⼀下secret值以完成第⼀步的解密

通过解密之后的固件提取文件系统中⼀个名为fw_unpacker的bin⽂件中寻找我们需要的内容:①字符串查找secret值:记一次Vigor3910路由器敏感溢出分析②需要复制我们需要的nonce到⼀个单独⽂件中:记一次Vigor3910路由器敏感溢出分析③这⾥需要针对enc_image进⾏操作,所以需要进⾏分割,将0xF3之前的全部删除,然后跑:记一次Vigor3910路由器敏感溢出分析第⼀次解密的exp:

import sys
from Crypto.Cipher import ChaCha20
def usage():
   print("{} path to file path to nonce".format(sys.argv[0]))
def go():
   if len(sys.argv) < 2:
       return usage()
with open(sys.argv[1],"rb") as f:
   data = f.read()
with open(sys.argv[2],"rb") as f:
   msg_nonce = f.read()

if len(msg_nonce) != 0xc:
   print("Invalid nonce len")
return

secret = b"0DraytekKd5Eason3DraytekKd5Eason"
cipher = ChaCha20.new(key=secret,nonce=msg_nonce)
plaintext = cipher.decrypt(data)
with open(sys.argv[1] + "_decrypt","wb") as f:
   f.write(plaintext)

if __name__ == "__main__":
   go()

随后将解密后的固件用010 Editor打开lz4加密,给出exp:

import sys
import os
# from Crypto.Cipher import ChaCha20
def usage():
print("Usage: {} image to extract".format(sys.argv[0]))
def go():
if len(sys.argv) < 2:
return usage()
with open(sys.argv[1],"rb") as f:
data = f.read()

data_start = data.find(b"x02x21x4cx18")
if data_start == -1:
print("LZ4 header not found")
return False

data_end = data.find(b"TRAILER!!!")
temp_end = data_end
while temp_end != -1:
data_end = temp_end
temp_end = data.find(b"TRAILER!!!",data_end+1)
# print(data_end)
if data_end == -1:
print("LZ4 trailer not found")
return False
data_end += 0x14-5
print("Found LZ4 from {:x} to {:x}".format(data_start,data_end))
filename_out = sys.argv[1] + "_fs.lz4"
with open(filename_out,"wb") as f:
f.write(data[data_start:data_end])

os.system("lz4 -d {}".format(filename_out))
return True


if __name__ == "__main__":
go()

原文始发于微信公众号(Th0r安全):记一次Vigor3910路由器敏感溢出分析

版权声明:admin 发表于 2022年12月27日 上午8:44。
转载请注明:记一次Vigor3910路由器敏感溢出分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...