Zyxel设备固件提取与口令破解

匿名者  905天前

背景介绍

在受客户之邀进行渗透测试过程中,我们利用弱口令成功拿下了Zyxel ZyWALL统一安全网关(USG)设备的管理权限,这些设备被用作分支机构的防火墙和VPN集线器。另外,这些设备通常是面向中小型企业的,而且很受欢迎,至少根据Shodan的结果来看确实如此。

1.png

获取管理权限后,我们有进一步转储了相关的配置,结果发现存储在这些设备上的一系列口令通过某种方式进行了加密。当我们在谷歌上搜索时,我们无法在互联网上找到任何关于这些口令是如何存储的公开信息。根据我们的观察,这些口令必须用可逆算法进行加密,因为它们是设备本身使用的口令,比如VPNPSK

1.png

由于我们有一些闲置的预算,我们决定在eBay上购买一台类似的设备,并花一些时间自己审计它。我们将在下一篇文章中为读者介绍针对该物理设备的分析结果。同时,设备到达之前,我们还可以先做一些准备工作,就是下面我们要介绍的内容。

作为Zyxel审计系列的第一篇文章,我们将为读者介绍如何提取ZyxelZyWALL统一安全网关(USG)设备的固件,并对加密的口令进行解密处理。

固件提取

首先,我们从官方网站下载了与客户部署的USG310设备相同的固件映像(4.104.70版本)。

我们开始研究4.10版的固件:文件410AAPJ2C0.bin实际上就是ZIP格式的固件映像。不幸的是,该ZIP归档是受口令保护的。在网上搜索一番之后,我们没有找到任何关于Zyxel公司使用的口令的信息。

然而,在随固件分发的PDF文件中,我们却找到了升级过程失败时的恢复方法。

1.png

如果上述方法不管用的话,还可以借助于一个较低级别的过程来实现恢复:

https://kb.zyxel.com/KB/searchArticle!gwsViewDetail.action?articleOid=006845&lang=EN

根据上述低级恢复指南中的介绍,我们可以看出系统是直接执行“.ri”文件来安装基本组件的,以便通过“.bin”文件来刷写固件。

于是,我们用binwalk提取了“410aapj2c0.ri”:

inode@stormbringer:w$ binwalk -e410AAPJ2C0.ri

DECIMAL       HEXADECIMAL     DEsc riptION

--------------------------------------------------------------------------------

512           0x200           uImage header, header size: 64bytes, header CRC: 0xF9EC0106, created: 2014-12-06 03:27:53, image size:4948010 bytes, Data Address: 0x5000000, Entry Point: 0x80101400, data CRC:0xD43F46E, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type:lzma, image name: "Linux Kernel Image"

576           0x240           LZMA compressed data, properties:0x5D, dictionary size: 8388608 bytes, uncompressed size: 16814648 bytes

inode@stormbringer:w$

其中包含下列文件:

inode@stormbringer:w/_410AAPJ2C0.ri.extracted$binwalk -e 240

DECIMAL       HEXADECIMAL     DEsc riptION

--------------------------------------------------------------------------------

0             0x0             ELF, 64-bit MSB MIPS32 rel2executable, MIPS, version 1 (SYSV)

5095576       0x4DC098        Linux kernel version 2.6.32

11385704      0xADBB68        gzip compressed data, maximumcompression, from Unix, last modified: 2014-12-06 01:57:21

11487616      0xAF4980        DES SP2, big endian

11488128      0xAF4B80        DES SP1, big endian

11511376      0xAFA650        CRC32 polynomial table, little endian

11910064      0xB5BBB0        Unix path: /usr/bin/magic-seed

11919441      0xB5E051        Unix path:/sys/module/perf_counters/parameters/counter

再次进行提取操作:

inode@stormbringer:w/_410AAPJ2C0.ri.extracted/_240.extracted$binwalk -e D65000

DECIMAL       HEXADECIMAL     DEsc riptION

--------------------------------------------------------------------------------

0             0x0             ASCII cpio archive (SVR4 with noCRC), file name: ".", file name length: "0x00000002", filesize: "0x00000000"

112           0x70            ASCII cpio archive (SVR4 with noCRC), file name: "zyinit", file name length: "0x00000007",file size: "0x00000000"

232           0xE8            ASCII cpio archive (SVR4 with noCRC), file name: "zyinit/zyinit", file name length:"0x0000000E", file size: "0x00040DEC"

266064        0x40F50         ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/etc_inittab", file name length:"0x00000013", file size: "0x00000BB8"

269196        0x41B8C         ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/e2fsck", file name length: "0x0000000E",file size: "0x0006B64C"

709204        0xAD254         ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/zld_mrd.ko", file name length:"0x00000012", file size: "0x00001788"

715356        0xAEA5C         ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/rw.zip", file name length: "0x0000000E",file size: "0x002106C8"

2879904       0x2BF1A0        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/mke2fs", file name length: "0x0000000E",file size: "0x0004239C"

3151288       0x3015B8        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/switchdev.ko", file name length:"0x00000014", file size: "0x0000AF10"

3196236       0x30C54C        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/zld_fsextract", file name length:"0x00000015", file size: "0x00017098"

3290728       0x323668        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/sw_cn60xx.ko", file name length: "0x00000014",file size: "0x00005418"

3312388       0x328B04        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/zld_udev", file name length:"0x00000010", file size: "0x0001347C"

3391488       0x33C000        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/db.zip", file name length: "0x0000000E",file size: "0x00001428"

3396772       0x33D4A4        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/zyinit_gpl", file name length:"0x00000012", file size: "0x00055128"

3745356      0x39264C        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/fwversion", file name length:"0x00000011", file size: "0x0000014A"

3745816       0x392818        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/switchdev_char.ko", file name length:"0x00000019", file size: "0x00005800"

3768480       0x3980A0        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/unzip", file name length: "0x0000000D",file size: "0x0002B8B0"

3946956       0x3C39CC        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/lkm.lst", file name length:"0x0000000F", file size: "0x00000050"

3947164       0x3C3A9C        ASCII cpio archive (SVR4 with no CRC),file name: "zyinit/platform_support.ko", file name length:"0x0000001B", file size: "0x00004CC8"

3966960       0x3C87F0        ASCII cpio archive (SVR4 with no CRC),file name: "init", file name length: "0x00000005", filesize: "0x0000000D"

3967092       0x3C8874        ASCII cpio archive (SVR4 with no CRC),file name: "TRAILER!!!", file name length: "0x0000000B",file size: "0x00000000"

inode@stormbringer:w/_410AAPJ2C0.ri.extracted/_240.extracted$

检查提取的文件,在zyinit二进制文件中找到了一些与固件有关的字符串。

通过分析,看看它是否启动了其他外部命令,特别是“zld_fsextract”命令:

1.png

在网上搜索这些可执行的二进制文件,只找到了一个有趣的URLhttps://www.dslreports.com/forum/remark,26961186),其中含有一些关于ZIP口令的信息。

1.png

在“zld_fsextract”二进制文件中搜索口令,很可能找出一些有用的线索,比如:

1.png

这些选项由“unzip”二进制文件使用参数“-p”中定义的特定口令来解压缩文件。根据网上找到的信息,我们认为该二进制文件似乎是根据二进制文件的名称或二进制文件的内容,以某种方式来计算解压口令的。

提取文件的最简单方法,就是模拟MIPS处理器并执行该二进制文件。

为此,先启动一个Linux/MIPS虚拟机,具体命令如下所示:

> wgethttps://people.debian.org/~aurel32/qemu/mips/vmlinux-3.2.0-4-5kc-malta

> wgethttps://people.debian.org/~aurel32/qemu/mips/debian_wheezy_mips_standard.qcow2

> qemu-system-mips64.exe -M malta-kernel vmlinux-3.2.0-4-5kc-malta -hda debian_wheezy_mips_standard.qcow2-append "root=/dev/sda1 console=tty0" -net nic -netuser,hostfwd=tcp:127.0.0.1:2222-:22

然后,使用“zld_fsextract”二进制文件来获取固件映像信息,具体如下所示:

root@debian-mips:~# ./zld_fsextract410AAPJ2C0.bin -s list

name                :kernel

scope               :-f kernelusg310.bin -fkernelchecksum -D /

nc_scope            :-f kernelusg310.bin

version             :2.6.32

build_date          :2014-12-06 11:27:35

checksum            :6e4e1ad212be0a8a3ce89484f3c5dc1e

core_checksum       :a028057f7c742ea52bd3d0408f38a673

name                :code

scope               :-f bmusg310.bin -f bmchecksum-f kernelusg310.bin -f kernelchecksum -d wtp_image -d db -i -D /rw

scope               :-d db/etc/zyxel/ftp/conf -D /

nc_scope            :-f fwversion -f filechecksum -fwtpinfo

version             :4.10(AAPJ.2)

build_date          :2014-12-09 08:51:18

checksum            :899be95dac4a5bdcfd2f694035f16746

core_checksum       :e25ab639d4ff432bb7ffdc8c1bd39be3

name                :WTP_wtp_image/400AAS4C0.bin

scope               :-f wtp_image/400AAS4C0.bin -D/db

nc_scope            :

version             :4.00(###.4)

build_date          :2013-08-31 20:36:43

checksum            :07773b3deb39a1dd9c2036201097529c

core_checksum       :07773b3deb39a1dd9c2036201097529c

name                :WTP_wtp_image/400AADG4C0.bin

scope               :-f wtp_image/400AADG4C0.bin -D/db

nc_scope            :

version             :V4.00(###.4)

build_date          :2013-08-31 20:35:40

checksum            :aabb0606887cec28a07b8598e699f027

core_checksum       :aabb0606887cec28a07b8598e699f027

root@debian-mips:~#

并使用zld_fsextract二进制文件提取固件,这里无需指定口令:

root@debian-mips:~# ./zld_fsextract410AAPJ2C0.bin ./unzip -s extract -e code

...

root@debian-mips:~#

root@debian-mips:~# ls -al /rw/

total 57192

drwxr-xr-x 3 root root     4096 Nov 23 12:56.

drwxr-xr-x 24 root root     4096 Nov 23 12:56 ..

-r--r--r-- 1 root root 58511360 Dec  6  2014 compress.img

drwxr-xr-x 5 root root     4096 Dec  9  2014etc_writable

-rw-r--r-- 1 root root      139 Dec  9  2014filechecksum

-rw-r--r-- 1 root root    21415 Dec  9  2014filelist

-rw-r--r-- 1 root root      326 Dec  9  2014fwversion

-rw-r--r-- 1 root root     1671 Dec  9  2014wtpinfo

root@debian-mips:~#

然后解压缩该新映像:

inode@stormbringer:w$ binwalk -ecompress.img

DECIMAL       HEXADECIMAL     DEsc riptION

--------------------------------------------------------------------------------

0             0x0             Squashfs filesystem, littleendian, version 4.0, compression:gzip, size: 58509745 bytes, 4958 inodes,blocksize: 131072 bytes, created: 2014-12-06 03:26:20

inode@stormbringer:w$

在看到上述流程可以在完全仿真的环境中正确工作后,我们决定让QEMU来仿真单个二进制文件。通过使用“strace”,我们可以快速检查“unzip”二进制文件是如何启动的;了解该过程有助于我们查找ZIP口令。

strace -f -s 199 qemu-mipsn32-static./zld_fsextract 410AAPJ2C0.bin ./unzip -s extract -e code

上述命令的输出结果如下所示:

1.png

这个计算ZIP口令的二进制文件是静态编译的,因此,要了解该口令是如何产生的并不容易,最重要的是我们很懒……

口令的加密算法

现在我们已经可以访问文件系统了,接下来,让我们开始寻找用于在配置文件中存储口令的算法的信息。在我们可用的配置中,所有的口令采用的格式都是4$,并在前面加上了下面的关键词:

  •    encrypted-key
  •    encrypted-keystring
  •    encrypted-password
  •    encrypted-presharekey
  •    password-encrypted
  •    wpa-psk-encrypted

第一步,确定这些关键字是由哪些可执行文件处理的:

inode@stormbringer:w$ grep"encrypted-" _compress.img.extracted/squashfs-root/bin/*

Binary file_compress.img.extracted/squashfs-root/bin/zysh matches

Binary file_compress.img.extracted/squashfs-root/bin/zyshd matches

inode@stormbringer:w$

在“zyshd”的代码中查找标识加密口令的字符串“$4$”:

1.png

然后,检查schrodinger例程,它用于生成盐:

1.png

加密是由以下代码负责:

1.png

最后,还会进行base64编码:

1.png

查看“rij_cbc_encrypt”函数内部,可以找到将我们引向AES算法的例程“rij_decrypt”。同时,函数的名称(RIJ=Rijndael)以及设置密钥使用的0xC0(即192)也证实了这一点:AES是少数支持192位密钥的加密算法之一。

查看加密例程内部,可以发现像Td0内存这样的AES参数;此外,我们也可以使用FindCrypt Ghidra插件来帮助识别相应的加密例程。

我们可以假设加密/解密函数的工作方式如下:

RIJ_cbc_encrypt(destination, source, len,unknown, IV, encryption/decryption byte)

接下来,我们只需要确定传递给函数的参数。

IV是:

1.png

加密密钥是:

1.png

所以:

aes_key ="001200054A1F23FB1F060A14CD0D018F5AC0001306F0121C"

aes_iv = "0006001C01F01FC0FFFFFFFFFFFFFFFF"

对于4.70版本的固件,也可以遵循相同的过程来识别$5$加密方案。

总而言之,对于以$4$开头的口令哈希值,算法具体如下:

iv = static_iv

key = static_key

salt = generate_8_bytes_from_random()

to_encrypt = salt + password (the passwordis repeated to reach the 80 bytes)

AES_SET_KEY(aes,key,192)

AES_DECRYPT(aes,cyphertext,to_encrypt,key,iv)

final_encrypted = base64(cyphertext)

final_string = "$4$" + salt +"$" + final_encrypted "$"

而以$5$开头的口令哈希值,算法如下:

iv = static_iv

key = static_key

salt = generate_8_bytes_from_random()

to_encrypt = salt + password (the passwordis repeated to reach the 80 bytes)

AES_SET_KEY(aes,key,192)

AES_DECRYPT(aes,cyphertext,to_encrypt,key,iv)

salt = generate_8_bytes_from_random()

to_encrypt = salt + password (the passwordis repeated to reach the 80 bytes)

AES_SET_KEY(aes,key,192)

AES_DECRYPT(aes,cyphertext,to_encrypt,key,iv)

step1 = base64(cyphertext)

salt1 = generate_8_bytes_from_random()

to_encrypt = salt1 + step1

AES_SET_KEY(aes,key,192)

AES_DECRYPT(aes,cyphertext,to_encrypt,key,iv)

final_encrypted = base64(cyphertext)

final_string = "$5$" + salt1 +"$" + salt2 + "$" + final_encrypted "$"

我们开发了一个解密工具,可以从以下网址下载:https://github.com/inode-/zyxel_password_decrypter

对于这些算法,另一种逆向分析方法是进行动态分析,但QEMU似乎对Zyxel使用的SoC的支持并不完美,并在大多数可执行文件上都会出现非法指令错误。在https://github.com/amir-mehmood/qemu-octeon-mips64上,好像有一个有效的QEMU补丁程序,但我们尚未对其进行测试。

最后,当我们收到物理设备后,发现文件系统中的二进制文件/usr/sbin/zencrypt也可以用来解密这些口令:

root@https://security.humanativaspa.it/zyxel-firmware-extraction-and-password-analysis/USG20-VPN:~# zencrypt -k'E8AzAwOyYBwVHJJjtUTDqdAxLDPIr/ncDNV5HCfZFRJlqhYkSqbGvX9BP06YyBg5fGp2HQrwtHsp9mQLNAtBeEIPejrUv5jw/ZRmUx20nuwCNK0UZdeklaFWc945oR3zWVupR2i/KakLhb9d46q72geNfFnXggbJdsl7ObjGKUNLfRF6tMnvxGtPO54PJKpL8E9Af4LAqStAAEPu3S70og8h9PzUER9/Qq246kyTfjONyyVF49EX1l+vg6rD0y+5UnHamBedqvzr/e7az469oViXUIxfMnr/CpMgR5hgzKn3efqldNVSEqmS07UN6CkjHiWaQgnDTxhc4tjbZQjaT3CGVpghF7W3GzmYtMqQlYQ$'

pluto

感谢您的阅读,我们将在下一篇文章中继续为读者介绍有趣的漏洞!


本文由secM整理并翻译,不代表白帽汇任何观点和立场

原文地址:https://security.humanativaspa.it/zyxel-firmware-extraction-and-password-analysis/


最新评论

昵称
邮箱
提交评论