# [Write Up] IFESR: IoT Firmware Emulation for Exploit and Security Research In this write-up, our team, Fisabilillah, utilized the Totolink EX200 router firmware as the exploitation target. The firmware was extracted and run through a firmware emulation approach using QEMU. This approach was chosen because it allows us to **execute the router's native operating system and services virtually**, without the need for physical hardware. The use of this method provides high flexibility in the reverse engineering and penetration testing process, while also ensuring experiments can be conducted in a controlled manner without the risk of damaging the original device. ![foto totolink](https://hackmd.io/_uploads/ByT83vh9ll.png) As is known, the Totolink EX200 router firmware contains a `Command Injection vulnerability`, where an attacker can inject malicious commands into the shell through a GET parameter. This vulnerability has been officially documented under the code `CVE-2021-43711`. ![image](https://hackmd.io/_uploads/Bkdy6_nqel.png) We highly recommend using `Ubuntu 18.04` OS to perform `QEMU` emulation. In our opinion, this Linux distribution is easier in terms of network interface management.Below are the steps and tools that need to be prepared. ``` Download link for Totolink EX200 firmware:http://totolink.net/data/upload/20210428/7979e841521515eb83b45aacf5b67f9a.zip Download Ubuntu 18 : https://releases.ubuntu.com/18.04/ubuntu-18.04.6-desktop-amd64.iso ``` ``` #Installing QEMU sudo apt-get install qemu sudo apt-get install qemu-user-static sudo apt-get install qemu-system #Install all the dependencies sudo apt-get install libglib2.0 libglib2.0-dev sudo apt-get install autoconf automake libtool #Install the dependencies required by the network bridge sudo apt-get install uml-utilities bridge-utils ``` After completing the download process for the Totolink EX200 firmware, the resulting file will appear as follows: ![2](https://hackmd.io/_uploads/H1uCRdhqex.png) Next, to extract the Totolink EX200 file, we can use the` unzip` command with the syntax` unzip (filename)`. The result will be as follows: ![4](https://hackmd.io/_uploads/HyG8-Yn9ge.png) The next step is to run Binwalk to perform validation. The objective is to examine the contents within the firmware and to ensure that the firmware file we are using is appropriate for the emulation target. At this stage, our primary goal is to extract all files embedded within the firmware binary file using the command `binwalk TOTOLINK_CS133EEN_EX200_WX005_8196E_SPI_4M32M_V4.0.3c.7646_B20201211_ALL.web` ![5](https://hackmd.io/_uploads/BkM2XYhcle.png) As can be seen from the analysis results, this firmware contains a `SquashFS `filesystem, several UNIX paths, and a file compressed with `LZMA `that is relatively large in size. To extract these files, we can use `binwalk` with the` -Me` option to extract the firmware contents recursively. `binwalk -Me TOTOLINK_CS133E-EN_EX200_WX005_8196E_SPI_4M32M_V4.0.3c.7646_B20201211_ALL.web` After the extraction process is complete, we will obtain a large number of files and directories resulting from the disassembly of the firmware, as shown in the following image. ![8](https://hackmd.io/_uploads/H1IrLK3cxx.png) The main focus of our attention is the `squashfs-root` directory. `SquashFS` is a `read-only` filesystem that allows for the compression of an entire filesystem or individual directories. By navigating into this directory, we can obtain the complete application filesystem schema, as shown in the following result. ![ll pada direktori squash-root](https://hackmd.io/_uploads/BkLSvY25lx.png) A tool named `Firmwalker` can be used to automatically analyze the filesystem and extract important files. However, in our experience, using this tool is not always straightforward. Furthermore, while alternatives such as using `FAT` for emulation are available, this approach is less ideal for reverse engineering purposes compared to `QEMU`. As an additional step to ensure the process runs correctly, a good practice is to identify the processor architecture of the analyzed firmware. This information is crucial as it will influence how the router firmware is executed within the emulation environment. Based on the analysis results, this `Totolink EX200 firmware` uses the `MIPS little endian architecture`. ![hasil meta data dari busybox](https://hackmd.io/_uploads/S1Hrtth5ll.png) Another important aspect to understand is how an application is spawned and performs its initialization process. On devices such as routers, information regarding this initialization process can typically be found in the `/etc/init.d/` directory. Since we are attempting to emulate a router that is managed through a `local web UI`, there is certainly a web server running as part of the system. The web server's initialization process can be found in the `rcS` file. By using the command `cat /etc/init.d/rcS`, the result will be as follows: ![hasil melihat direktori rcs (di dalamnya)](https://hackmd.io/_uploads/HyyZ2Fh9xe.png) In this case, the router uses the `Lighttpd` web server, and the following command shows how this process is launched by the system. Since the architecture used is `MIPS little endian`, we need to use` qemu-mips-static` to run this router firmware on the localhost system. The command used is as follows: ``` cp $(which qemu-mips-static) . sudo chroot . ./qemu-mips-static lighttpd -f lighttp/lighttpd.conf -m lighttp/lib/ ``` However, when that command is executed, an error message appears indicating that the process failed because the pid-file was not found, as shown in the following output. ![hasil chroot](https://hackmd.io/_uploads/HJ5JCt39gl.png) If we review the contents of the `/etc/init.d/rcS` file again, it is evident that the initialization process requires the existence of the following files. ![hasil error lighhttpd](https://hackmd.io/_uploads/BJbLAYh5le.png) This is not a complicated issue; the file is indeed required but currently does not exist, so we can create it manually. Under normal conditions, a file like this is typically generated automatically when the system performs a full boot process for the first time. Proceed by creating the `lighttpd.pid `file in the `squashfs-root` directory. ``` ls mkdir run touch lighttpd.pid ``` ![membuat file di var run lighttpd](https://hackmd.io/_uploads/S1e1l92cll.png) After the file is created, when the command is executed again, the process can run successfully and we can now access the router's interface page via the web. ![menjalankan perintah chroot server start](https://hackmd.io/_uploads/BJ45x9n5ex.png) ![hasil dari tootlink router](https://hackmd.io/_uploads/H1a9gq39gx.png) The challenge is that the system most likely is not running perfectly, because the paths and` symlinks` present in `/etc/init.d/rcS` are either incorrect or contain errors. ![hasil dari mount user data](https://hackmd.io/_uploads/r15C-52cxe.png) Indeed, this issue could be fixed manually if one is willing to do so. However, it is highly likely that we would encounter numerous obstacles due to several important folders not being mounted. Therefore, a better approach is to use the `fresh system mode` method. By changing the paths to `UNC` paths pointing to the `/squashfs-root` location, we can run it within an isolated virtual system without the risk of damaging the host system. I will not discuss the technical details of how the system mode works, as it is not strictly necessary. To implement this approach, we can use the `start-mipsel.sh` script along with the following support files: https://people.debian.org/~aurel32/qemu/mips/ ![image](https://hackmd.io/_uploads/S1YdH52cge.png) After the support files have finished downloading, the next step is to create a new script file using the command:nano `start-mipsel.sh` Then, input the following script content and save it:`qemu-system-mips -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mips_standard.qcow2 -append "root=/dev/sda1" -netdev tap,id=tapnet,ifname=tap0,script=no -device rtl8139,netdev=tapnet -nographic`The next step is to configure the network interface on the host to enable communication with the emulated system. The commands used are as follows: ``` # HOST sudo brctl delif virbr0 tap0 2>/dev/null sudo ifconfig virbr0 down 2>/dev/null sudo ifconfig tap0 down 2>/dev/null sudo brctl delbr virbr0 2>/dev/null sudo tunctl -d tap0 2>/dev/null ``` ![menjalankan sudo di host](https://hackmd.io/_uploads/SkRmlfTqlx.png) ``` # HOST sudo brctl addbr virbr0 sudo ifconfig virbr0 192.168.100.1/24 up sudo tunctl -t tap0 sudo ifconfig tap0 192.168.100.2/24 up sudo brctl addif virbr0 tap0 echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward ``` ![jalankan perintah sudo 2 host](https://hackmd.io/_uploads/rJ1dxzpqll.png) After the network interface configuration on the host is completed, the next step is to run `QEMU` using the command`./start-mipsel.sh` This command will execute the previously created script and initiate the firmware emulation process. The command execution will produce terminal output as shown below. ![hasil start mips sh](https://hackmd.io/_uploads/rJ80ZMp5xg.png) The next step is to activate the network interface on the emulated system so it can be used for communication with the host. To log into the `QEMU` system, use the following credentials: ``` Username: root Password: root ``` ![login qemu mips](https://hackmd.io/_uploads/BkcJQz65ll.png) After successfully logging in, the next step is to configure the network interface on the `QEMU` system to enable connectivity with the host. Use the following command: ``` # QEMU ifconfig eth0 192.168.100.10/24 up route add default gw 192.168.100.1 ``` The next step: From the main machine (Ubuntu host), use the `SCP `command to copy the `/squashfs-root/` directory into the `QEMU` environment. `scp -r squashfs-root/ root@192.168.100.10:/root/` The command above will copy the entire contents of the extracted firmware directory `(squashfs-root)` into the` /root/` directory on the` QEMU` system with the `IP address 192.168.100.10.` ![transfer file menggunakan scp pada hosts](https://hackmd.io/_uploads/rk0yrGacxe.png) After the file transfer process from the host to the `QEMU` system is completed, the result will appear as follows ![file berhasil di transfer pada debian mips](https://hackmd.io/_uploads/rkqUrfa9ge.png) Next, one of the most crucial steps is to perform the mounting process so that directories and critical system files can be accessed by the emulation environment. Use the following command: ``` mount -o bind /dev ./squashfs-root/dev mount -t proc /proc ./squashfs-root/proc mount -o bind /sys ./squashfs-root/sys ``` After the `mounting` process is complete, the next step is to run the system by changing the root filesystem using the` chroot` command. This allows us to enter the `firmware's filesystem` and execute its native shell. `chroot ./squashfs-root/ /bin/sh` then start the server with the command `lighttpd -f lighttp/lighttpd.conf -m lighttp/lib/` The result will be as follows: ![server berhasil di jalankan di mips debian](https://hackmd.io/_uploads/H1maLzTcxx.png) After all the steps have been executed, the application can be accessed via a browser by navigating to the address: `https://192.168.100.10`. On that page, the web interface of the `firmware` being executed within `QEMU` will be displayed. ![berjalan pada web server 192.168.100.10](https://hackmd.io/_uploads/BJn5vzp5lx.png) Next, we performed a scanning process using the Nmap tool with the following command `nmap -A -sV 192.168.100.10 `The scan results indicate that the emulated router firmware is running on port 80 and using the `Lighttpd 1.4.20` web server, as displayed in the following image. ![port scaning](https://hackmd.io/_uploads/SkZU3GT5gg.png) The next step is to analyze the login form on the router firmware by utilizing `Burp Suite` and the `Tamper Request` feature. After `Burp Suite is running`, open the Open Browser menu to `initiate the testing process and capture HTTP/HTTPS traffic from the application`. ![open browser burpsuite](https://hackmd.io/_uploads/Syh9TGpqll.png) ![intercept di on kan](https://hackmd.io/_uploads/ryd7176qex.png) After the browser is open and the `Intercept` feature in `Burp Suite` is activated, the next step is to input credentials into the login form via the browser using the credentials: ``` Username: admin Password: admin ``` Then, press Enter to submit the request. The resulting request will be captured and displayed on the Intercept tab in Burp Suite, as shown in the following image. ![send rto repeater](https://hackmd.io/_uploads/H1yIV76qle.png) After the `Intercept` tab successfully captures the request from the browser, the next step is to right-click on the request and select the `Send to Repeater` option. This will move the request to the Repeater tab, making it easier to modify the existing parameters. Then, click` Send` to submit the request, as shown in the following image. ![hasil send to repeatrer](https://hackmd.io/_uploads/H1r4OQpqxe.png) At this stage, the application's display may appear imperfect or broken, but it is actually the correct login page of the application. It is possible the interface seems problematic, making it essential to perform validation, code inspection, or a sanity check. If it is genuinely broken, re-examine the `mounting` process that was carried out and compare it with the firmware initialization scripts located in the `/etc/init.d/*` directory, as the issue is commonly caused by incorrect `symlinks` Nevertheless, at this point, the application should be analyzable using Burp Suite to capture requests and interact with the application. However, obstacles may not end here. As seen in the following result, an error message appears:`Cste MD5 failed` The only effective way to fix this error is to perform a` reverse engineering` process. To find its root cause, the simplest step that can be taken is to use the command `grep -rnl getCsteMD5` to search for this error message within the source code or binary files. ![downlaod file csteg untuk di analisis](https://hackmd.io/_uploads/SJa2AQp9eg.png) Next, the file `cstecgi.cgi` was analyzed using `Ghidra`. After performing a `string search`, it was discovered that the error originates from the function `FUN_00403b40`, which is triggered when the data stream fails to read a file named `cstemd5`. ![reverse engineering csteg](https://hackmd.io/_uploads/HJQcyV65el.png) By adding a file named `/var/cstemd5` containing a random MD5 string, the issue can be resolved. The command: `echo $RANDOM | md5sum | cut -d' ' -f1 > /var/cstemd5` will generate and output an MD5 hash as shown in the following image. ![image](https://hackmd.io/_uploads/SJQ0GVpcxl.png) At this stage, the emulation environment is ready to be used for the **reverse engineering** process and vulnerability research. As a demonstration that QEMU is running stably and can be used to develop and **test a Proof of Concept (PoC)**, a simple exploitation example is shown below, targeting a clearly visible Command Injection vulnerability in the `TOTOLINK EX200 firmware`. ![reverse engineering downloadFlile cgi](https://hackmd.io/_uploads/S1TKm4T5ll.png) ``` pcVar1 = getenv("QUERY_STRING"); memset(acStack_590,0,0x200); memset(acStack_390,0,0x200); sprintf(acStack_590,"echo QUERY_STRING:%s >/tmp/download",pcVar1); //can be manipulated. system(acStack_590); ``` ![reverse engineering downloadFlile cgi](https://hackmd.io/_uploads/Bk7SVN6qxg.png) In the` downloadFile.cgi` function, the `QUERY_STRING` parameter variable represents the contents of the `GET request`. If we can manipulate the value of the `QUERY_STRING`, there is an opportunity to perform **Command Injection**. As shown in the following result, this attack was successfully executed, where we were able to run a simple command to display the date `(date)` through this injection. ![image](https://hackmd.io/_uploads/HJ64I4acll.png) The following demonstrates proof of successfully performing an `arbitrary read `on the emulated device within the `QEMU` environment. This attack was successfully carried out via **Command Injection** on the target, allowing an attacker to view the contents of the device's directories. The result displayed in the image **shows that the directory structure is identical to that found on the original router's shell**. ![image](https://hackmd.io/_uploads/HJwtkHaceg.png)