原文始发于Maurizio Agazzini:Zyxel firmware extraction and password analysis
Backstory
During a red teaming exercise conducted for one of our customers, we abused weak passwords to obtain an administrative access to some Zyxel ZyWALL Unified Security Gateway (USG) appliances that were used as both firewalls and VPN concentrators in their branch offices. These appliances are targeted at small and medium businesses and are somewhat popular, at least according to Shodan.
Thanks to our administrative access, we were able to dump the configurations and we noticed that a series of passwords stored on these devices were encrypted in some way. When we did a Google search we could not find any public information on the Internet about how these passwords were stored. Based on our observations, they had to be encrypted with a reversible algorithm because they were passwords that the device itself used, such as the PSKs of VPNs.
Since we had some spare budget, we decided to buy a similar device on eBay and spend some time auditing it on our own. Our next articles will cover the results of our analysis carried out on the physical device. In the meantime, let’s focus on the work we did while we were waiting for the device to arrive.
In this first article of our Zyxel audit series we will cover firmware extraction and password decryption against Zyxel ZyWALL Unified Security Gateway (USG) appliances.
Firmware extraction
First of all, we downloaded from the official website the same firmware images (version 4.10 and 4.70) for the USG310 device that were deployed by our customer.
We started working on version 4.10 of the firmware: the file 410AAPJ2C0.bin is the firmware image in ZIP format. Unfortunately, the ZIP archive was password protected. Searching online we were unable to find any information on the passwords used by Zyxel.
In the PDF documents distributed with the firmware, however, a recovery method is described in the event that the upgrade procedure is unsuccessful.
A lower level procedure is also available in case the previously described method does not work:
https://kb.zyxel.com/KB/searchArticle!gwsViewDetail.action?articleOid=006845&lang=EN
Based on the information in the low level recovery guide we can assume that the “.ri” file is directly executed by the system to install the fundamental components in order to then be able to flash the firmware from the “.bin” file.
We extracted “410AAPJ2C0.ri” with binwalk:
And the files inside it:
And again:
Looking at the extracted files, it is possible to identify the “zyinit” binary, which contains some firmware related strings.
By analyzing it, it is possible to see that it launches other external commands, in particular the “zld_fsextract” command:
Searching online for these executable binaries, only an interesting URL was identified (https://www.dslreports.com/forum/remark,26961186), which gave us some information about the ZIP password:
Searching in the “zld_fsextract” binary for the password, it is possible to identify some good starting points for the analysis, like this one:
These options are used by the “unzip” binary to unzip a file with a specific password which is defined in the parameter “-P”. Based on information found online and on a quick analysis, it seems that the binary calculates the unzip password in some way based on the binary name or the binary content.
The fastest way to extract the files is to emulate the MIPS processor and execute the binary.
Launching a Linux/MIPS virtual machine:
Getting firmware image information using the “zld_fsextract” binary:
And using the zld_fsextract binary to extract the firmware without the need to specify a password:
Then uncompressing the new image:
After seeing that the process worked correctly with a fully emulated environment, we decided to try the single binary emulation provided by qemu. By using “strace” we can quickly see how the “unzip” binary was launched to find the ZIP password.
Here is the output.
The binary that calculates the ZIP password is statically compiled, therefore it is not so easy to understand how that password is generated, and above all we are lazy…
Password encryption algorithm
Now that we have access to the filesystem, let’s start looking for information on the algorithm used to store passwords in the configuration files. In the configurations available to us, all passwords used the $4$ format and were preceded by the following keywords:
- encrypted-key
- encrypted-keystring
- encrypted-password
- encrypted-presharekey
- password-encrypted
- wpa-psk-encrypted
First step, identify which executables deal with these types of keywords:
Looking in the code of “zyshd” for the string “$4$” which identifies the encrypted password:
Looking inside the schrodinger routine. This part generates the salt:
Encryption is performed by the following code:
And then the BASE64 encoding at the end:
Looking inside the “RIJ_cbc_encrypt” function, it is possible to identify the routine “RIJ_decrypt” which leads us to the AES algorithm. This is also confirmed by the name of the function (RIJ = Rijndael) and by the 0xC0 used on the set key, which is 192. AES is one of the few encryption algorithms that support 192-bit keys.
Looking inside the encryption routine, it is possible to identify AES parameters like Td0 memory; it is also possible to use the FindCrypt Ghidra plugin that helps identify the encryption routines in use.
We can assume that the encryption/decryption function works as follows:
At this point we only need to identify the parameters passed to the function.
The IV is:
The encryption key is:
So:
The same process can be followed on the firmware version 4.70 to identify the $5$ encryption scheme.
To summarize, in the case of a password hash starting with $4$ the algorithm is as follows:
In the case of a password hash starting with $5$ the algorithm is as follows:
We developed a decryption tool that can be downloaded from: https://github.com/inode-/zyxel_password_decrypter
Another possible way to reverse these algorithms is to use dynamic analysis, but it seems QEMU does not fully support the SoC used by Zyxel and generates some illegal instruction fault on most executables. There is a potentially working QEMU patch at https://github.com/amir-mehmood/QEMU-Octeon-MIPS64, but we did not test it.
Finally, when we received the physical device we found out that the /usr/sbin/zencrypt binary present in the filesystem can be used to decrypt these passwords as well:
Stay tuned for our upcoming articles in this series, along with some juicy vulnerability disclosures!