Team82 Logo Claroty
Return to Team82 Research

Hack The Emulated Planet: Vulnerability Hunting on Planet WGS-804HPT Industrial Switches

/

Introduction

Emulators such as the open-source, cross-platform QEMU framework are invaluable tools for researchers conducting vulnerability research. QEMU and other emulators act as great testing environments where software and firmware can be analyzed for exploitable vulnerabilities. They can also be taken a step further for testing exploits within a safe space. 

For Team82, QEMU and other emulation platforms are center stage in much of our research, in particular where it may be difficult to obtain an actual target device. In this blog, we will explain how we used QEMU to emulate the relevant system components of Planet Technology Corp’s WGS-804HPT Industrial switch, and how it was used to uncover three vulnerabilities that could allow an attacker to remotely execute code on a vulnerable device. The vulnerabilities include separate buffer and integer overflow vulnerabilities and an OS command injection flaw; we were able to develop an exploit that leverages these bugs and remotely runs code on the device.

These switches are widely used in building and home automation systems for a variety of networking applications. An attacker who is able to remotely control one of these devices can use them to further exploit devices in an internal network and do lateral movement. We privately disclosed these vulnerabilities to Taiwan-based Planet Technology, which addressed the security issues and advised users to upgrade firmware in the device to version 1.305b241111.

Our Research Target: Planet WGS-804HPT

The Planet WGS-804HPT industrial switch is designed to be used in building and home automation networks to provide connectivity of internet of things (IoT) devices, IP surveillance cameras, and wireless LAN network applications. The WGS-804HPT is equipped with a web service and SNMP management interface.

Planet WGS-804HPT Industrial switch.


Obtaining the WGS-804HPT Firmware

One of the first steps of any embedded device research project is to obtain the contents of the firmware that is deployed on the target device. The firmware is valuable because it contains the most important components of a functional device, without it the device will be as good as a paper weight. These components include:

  • System configurations

  • Operating system (kernel)

  • File systems


This stage of research is very important and in many cases determines early on the chances for a successful project. In our case, this project was no exception and we were able to find the target’s firmware image on the vendor’s website.

Planet Technology's firmware download interface.

As with many embedded IoT devices, the Planet WGS-804HPT industrial switch provides owners with a management interface operable through a web browser. This management service was the component of the system we chose to focus on during our research, because it is the main component allowing a client to control their device and is most commonly exposed to the network. 

How To Handle A Firmware File

Now all we need to do is to extract the filesystem of this platform firmware, so we can actually begin finding bugs and vulnerabilities in binaries of the services running on this device. This is a common task every IoT and embedded device researcher undergoes in their research process. As such, several solutions have been developed by the open source community to aid with this, including:


In our case we used the utility binwalk to extract any applicable component of the system from the firmware file we have.

We downloaded the binwalk repository and followed building instructions according to the documentation:

git clone https://github.com/ReFirmLabs/binwalk.git
sudo ./binwalk/dependencies/ubuntu.sh
cd ./binwalk
cargo build --release
ls ./target/release/
binwalk  binwalk.d  build  deps  examples  incremental  libbinwalk.d  libbinwalk.rlib

And we have our binwalk utility built and compiled. All we need to do now is to use this tool to extract the filesystem of our target device.


Deep inside the matryoshka-doll like folders structure we discover the squashfs filesystem with the device root filesystem.

The squashfs root filesystem of the device.

In the squashfs filesystem, we see it contains the device service’s related components such as assets used with the web server of the device.

As we look further into this filesystem we find that the web server on this device is a variation of the popular embedded web server project called the Boa web server.

We want to have this web server up and running and so we need to find a way to run this application and have it functional with this filesystem. It could have been pretty easy if not for the fact that this device is a MIPS 32-bit architecture based system. And so to do this we will utilize emulation as our means for setting up this web server.

An Introduction to Qemu: An Emulation Toolset

Emulation is the act of reproducing an operation based on a different system architecture on a host machine. This is done by utilizing CPU instruction simulations and bridging OS effects and interaction between guest and host machines.


A very popular and highly maintained open source emulator called Qemu has been developed to facilitate and streamline the act of system and process emulation on a wide range of architectures. You can also find this tool’s repository in github and in almost any updated system package manager.

QEMU has more than 5,700 forks.

Qemu can be used in two ways:

  • User space emulation: Emulating a single executable in a specific guest architecture context.

  • System emulation: Emulating a full system including its kernel, I/O peripherals, drivers in a specific architecture context.

In this section we are going to demonstrate how one would use each option in a general manner, and later present how we use user space emulation for our research use case.

Qemu User Emulation

The first thing we need to do is to install the toolset provided with qemu.

sudo apt install qemu qemu-user qemu-user-static

Now we can go to the directory containing our target executable and prepare our emulation environment. In our case we are going to emulate the binary ps. To emphasize the need for environment setup we are going to run this command using qemu and see what happens. By doing so we also demonstrate one of the potential hurdles one may stumble upon.


Trying to emulate ps without an environment setup.

As you can see, the executable is not emulated properly yet and instead of the regular expected prompt of this command we see a message stating that an error occurred while trying to emulate it. The message hints at the root of the problem: we are missing an important component in the loading routine of the binary, /lib/ld-uClibc.so.0. This is actually the dynamic linker which is in charge of linking shared objects (dynamic libraries) into our target program. 

To solve this problem all we need to do is to find the corresponding missing library, which in our specific case is a dynamic linker of a MIPS 32bit system and place it in the location where it is expected to be at /lib.

BUT WAIT!

Before cluttering your host machine with cross-architecture libraries placed in important locations of the filesystem and possibly creating headaches in the future, we need to find a way to make qemu and the emulated executable think they access those important locations in the filesystem while actually accessing the required libraries from sources/locations we specifically created for our task. And there is a perfect solution just for that: chroot.

A chroot system command.

The chroot command is actually a user space wrapper for the syscall chroot implemented in the Linux kernel. This command allows us to change the root directory context of a specific process in the operating system and by doing so we can create a facade for the application to believe its running in its native environment when in fact we have fine-grained control over the assets it reaches to in the filesystem.

Having the basic understanding of the chroot command, we can start our filesystem environment setup. What we need to do is to create a /lib directory and place in that folder the required libraries our emulation target needs.

Setting up a filesystem environment for userspace application emulation.

Now we need to bring the qemu-mips-static application into our fake root directory so we can use it in our chroot context.

Copying qemu-mips-static into our fake root directory

Let’s try to emulate the target again:

We are not there yet, and this is actually reasonable because the library we brought has a different name than the name of the required library the emulation needs. But we believe this is the correct library, so let's create a symlink to this and try again.

Retrying our emulation; we have progress.

We need libc.so.0 also, in our case this is actually an alias to the libuClibc-0.9.28.so so we will bring it and try again.

Our emulation is almost complete.

So we have successfully emulated the executable actually, but we have one last problem; our fake root filesystem we chroot into doesn’t have a /proc directory that allows monitoring of OS processes operation, but there is a solution for that also. We need to create a /proc folder and mount the proc filesystem of our host to this directory. Notice that this means that our host system and guest emulated program share their view of the system processes.

Mounting the host proc filesystem to the guest fake root filesystem /proc directory

Trying again, we have a successful run of our emulated target executable.

Successful emulation of our ps executable target.

Now that these steps are complete and we have emulated a target executable in userspace, we will use this knowledge to aid us with our vulnerability research of the Planet WGS-804HPT industrial switch embedded device.

Qemu System Emulation

System emulation with qemu is a little bit more complicated, but following the guidelines provided with the documentation for the tool, one can quite easily set up a working environment and boot a working emulated system. Using the system emulation capabilities can come in very handy when fronted with multi-component system security research.

As this toolset is rich in features and options, we are going to focus on our most common use case for this aspect of qemu. And so we will boot up a Debian-based distribution of the Linux operating system supporting MIPS 32-bit architecture- based systems.

As we began previously with userscape executable emulation with qemu, we also need to install qemu-system emulation toolsets.

sudo apt install qemu-system

Next, we will create a directory that will contain the artifacts necessary to boot a working Linux Debian system for MIPS architecture:

  • Linux kernel: cross-compiled specifically for MIPS architecture

  • Root filesystem: Debian distribution

One can find this artifacts in release form, in a plug-and-play manner for emulation usage in the following site:

https://people.debian.org/~aurel32/qemu/mips/

Note that you can actually find in this openly accessible directory a README.txt file with clear instructions for setting and booting this Debian-based system emulation setup.

We download these artifacts:

wget https://people.debian.org/\~aurel32/qemu/mips/vmlinux-3.2.0-4-4kc-malta && wget
https://people.debian.org/\~aurel32/qemu/mips/debian_wheezy_mips_standard.qcow2

Downloading necessary artifacts for debian system emulation using qemu

And let’s run the following command after successfully downloading the kernel and filesystem:

qemu-system-mips -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0"

Running the command above and getting the emulated system to boot up in new window

As you can see this is quite simple given the right resources, and yet for more elaborate and intricate setups we do need to dig a little deeper. But this is a topic for its own dedicated blog post.

Emulating WGS-804HPT Web Service

Knowing now how to emulate a simple userspace application and a full operating system we can go ahead and tackle our original goal of emulating the web service provided by the WGS-804HPT industrial switch for vulnerability research and exploit development.

We already have the firmware of the device and managed to extract the filesystem out of it. All that remains is to set up the environment for emulation.

The first thing we do is to go into the root directory of our extracted squashfs filesystem, which in our case is a ./squashfs-root/0 directory, and copy qemu-mips-static to this location.

Copying qemu-mips-static utility to our root directory

Then we can mount necessary filesystems used commonly by working operating systems. We run the following commands inside the root directory of our emulated filesystem.

sudo mount -t proc /proc proc/ 
sudo mount --rbind /sys sys/ 
sudo mount --rbind /dev dev/

Something nice about having an entire embedded device filesystem extracted out of a firmware file is that sometimes it only requires you to do minimal adjustments to get it into a state where one could emulate a single executable from the system. 

The real challenge is when the system has highly coupled components interacting with each other and dependent on specific peripherals that are not accessible. This observation is key to understanding that being able to emulate an embedded system is often a gradual process with trial and error.

In our case, we deliberately chose a target that doesn’t have much coupling to other system services, which effectively means it can be emulated alone and work in a functional operating state.

What is a CGI?

Common Gateway Interface (CGI) scripts are a standard way used to enable web servers to interact with OS programs; CGIs are often scripts or executable files. A CGI interface allows the web server to create dynamic web pages, which are designed according to the user's request. This concept is very common in embedded systems.

The way CGI interfaces work is by translating HTTP requests from a client into a context provided to the underlying program running on the operating system. For instance the HTTP headers are supplied by environment variables and the raw body content is inserted into the standard input of the program.

Finding Vulnerabilities in dispatcher.cgi

The Planet WGS-804HPT industrial switch provides a web service using the boa webserver. The boa web service delegates pre-authenticated client requests to the dispatcher.cgi. This is an endpoint CGI interface that we are interested in analyzing and finding vulnerabilities because it is exposed and accessible for unauthenticated clients, making it suitable as a security attack surface.


Statically analyzing the dispatcher.cgi, we discovered a stack-based buffer overflow that can be exploited to achieve pre-authentication remote code execution. The vulnerability exists in an unsafe usage of the standard function sprintf to copy an id cookie value into a char array located on the stack without any sanity checking of the size of the copied value.

dispatcher.cgi main function - copying of user controlled id cookie value into a 64 bytes long buffer stored on the stack

This is a relatively simple primitive that provides an attacker with the ability to redirect code execution.

The cgi uses a specific cookie named id for client session management, the code checks if there exists a specific file (/tmp/cookie_%s) with the session id to determine if the request is in an active client session. The file existence check is done before verifying the credentials for authentication to determine if a client is already logged in with an active session. This means that the vulnerable code flow of the function is accessible in a pre authentication context and can be exploited by attackers without providing valid credentials.

Exploit Development

The next step in our research was to test the discovered vulnerability and create a working PoC to demonstrate exploitability and its impact. In order to develop our working PoC, we will use our knowledge of Qemu userspace program emulation, starting with emulating the whole boa web server and verifying we are able to interact with it.

Emulating the Boa web server.

This results in a working web service emulation setup that is up and running.

A working emulated Boa web server

Doing this will allow us to test the web service when we have a working exploit. But for our exploit development, we need to be able to debug the dispatcher.cgi CGI process. And so we will actually begin by just running the dispatcher.cgi program with a remote debugger attached to it. This is actually possible because qemu provides the option to initialize a gdb-server listener interface to debug an emulated application, below. 

Remote debugging using attached gdb-server from qemu to emulated program

Now having an ability to debug our dispatcher.cgi program we can start developing our exploit.

One of the first things to do when trying to develop our exploitation technique is to check the memory security mitigation applied to our target executable. 

Verifying the different protections used on the executable - NX bit is disabled and no stack canaries that mitigate the vulnerability exploitation

In this case, we are lucky to have our target without confining security mitigations on the executable. As such, we relied on the fact that the executable is compiled without the NX bit enabled which means the stack is also executable. This means it is possible to embed a shellcode in our request cookie and later jump into the stack where our payload shellcode is stored.

Our final shellcode invoked the execve syscall with controlled parameters also found in our payload on the stack and referenced using the $sp register as a base to offset from.

Our final shellcode in mips 32-bit assembly

We tried to make the shellcode as simple as we can to make it small and easy to develop.
The shellcode is composed from three main parts:

  1. Setting the execve syscall arguments in the corresponding registers:

    • $a0: Executable to invoke

    • $a1: Program arguments, separated by null bytes

    • $a2: Program environment variables

  2. Null bytes placement, which is required to set arguments boundaries. This is done with shellcode instructions because we are limited in null bytes placement inside our payload itself.

  3. Invoking the execve syscall to trigger our OS command.

Attempting to exploit this vulnerability with our python PoC script, we managed to control the code flow and achieve code execution. We then divert the code into our controlled shellcode and gain remote OS command execution capability.

Exploitation attempt inside our debugging environment - Invoking a shell script which creates the /pwn file

Summary

We found three vulnerabilities in Planet Technology’s WGS-804HPT industrial switches that could be chained and exploited to gain remote code execution on the device. The vulnerabilities were privately disclosed and fixed by the vendor. 

In this blog, we explained the importance of emulators such as the open-source QEMU framework to cybersecurity research. QEMU and other emulators allow researchers to emulate operating system components for vulnerability and exploit testing in a safe environment. This is especially crucial when equipment is not physically available to a researcher. 

QEMU was essential to our success in finding the three vulnerabilities in the Planet Technology industrial switch. We were able to emulate critical components of the device, understand where vulnerabilities may be uncovered, and managed to develop PoCexploits to present probable impact to the device.

Stay in the know Get the Team82 Newsletter
Related Vulnerability Disclosures
Claroty
LinkedIn Twitter YouTube Facebook