Fuzzing IoT devices for Memory corruption 0' Days.
This article is about discovering the memory corruption vulnerabilities in IoT Device, Upon reading this article you will understand from setting up device for fuzzing to developing a complete working exploit. what we called it Zero to hero kind of stuff also you can expect a lot of memes and some extra ज्ञान..
Before we start I would like to give some basics about the post and terms which we are using here.
IoT Devices generally consist of RISC mechanism those who are not able to recollect this you can remember your old days of engineering where you might have broke your head for understanding the working of 8041/8051 micro-controllers. so RISC stands for Reduced Instruction Set Computer and below are the list of processor which you can see widely used in IoT.
- ST Micro-controller.
- MediaTek MT3620.
- Quectel BG96.
There are plenty of resources available on internet to read/explore about this stuff. so suggest have a look at datasheets of the processors to understand few bits of it in this example we are taking a device which is running on MIPS.
Below is the short view on MIPS Registers, Taken from http://www.cs.uwm.edu/classes/cs315/Bacon/Lecture/HTML/ch05s03.html I generally have a printout of this on my desk.
|Register Number||Conventional Name||Usage|
|$0||$zero||Hard-wired to 0|
|$1||$at||Reserved for pseudo-instructions|
|$2 - $3||$v0, $v1||Return values from functions|
|$4 - $7||$a0 - $a3||Arguments to functions - not preserved by subprograms|
|$8 - $15||$t0 - $t7||Temporary data, not preserved by subprograms|
|$16 - $23||$s0 - $s7||Saved registers, preserved by subprograms|
|$24 - $25||$t8 - $t9||More temporary registers, not preserved by subprograms|
|$26 - $27||$k0 - $k1||Reserved for kernel. Do not use.|
|$28||$gp||Global Area Pointer (base of global data segment)|
|$f0 - $f3||-||Floating point return values|
|$f4 - $f10||-||Temporary registers, not preserved by subprograms|
|$f12 - $f14||-||First two arguments to subprograms, not preserved by subprograms|
|$f16 - $f18||-||More temporary registers, not preserved by subprograms|
|$f20 - $f31||-||Saved registers, preserved by subprograms|
The GNU Debugger is a portable debugger that runs on many Unix-like systems and works for many programming languages, including Ada, C, C++, Objective-C, Free Pascal, Fortran, Go, and partially
BusyBox is a software suite that provides several Unix utilities in a single executable file. It runs in a variety of POSIX environments such as Linux, Android, and FreeBSD, although many of the tools it provides are designed to work with interfaces provided by the Linux kernel
Also assuming that readers are familiar with Burp Suite, A = x41,B = x42, Metasploit.
Setting Up Device.
The device which is used in example, I manage to get the ssh credentials for device by reversing firmware and few binaries, Some guys might be thinking if you got a root or a shell then why to dig further and the reason is we are researchers we just don't have to hack a device for once, We have to find out all the possible way to hack the device so that we can save it from attackers. so once i got the shell i generally check for the busybox and available commands from busybox in device. so below was the output of busybox command which shows that device don't have netcat with listener mode and and not so common to for transferring files to device or from device to linux.
Getting right Busybox.
So the first challenge was to get my full busy box to the device and install it. after lil more analysis i found the command called ftpget which allow to download the file to device via ftp, So the next step was very simple i setup vsftpd on my machine host the right busybox o my /srv and then download it to device below was the flow for installation of busybox.
- cd /tmp --> as / was not writable
- ftpget 192.168.1.100 busybox busybox-mips. --> downloading busybox.
- mkdir ./bin --> create directory for installing busybox.
- ./busybox --install -s ./bin --> to install busybox.
- PATH=/tmp/bin:$PATH --> adding this path to real path.
And here we go upon this we get the complete busybox.
Getting Fuzz Ready.
For fuzzing we need the access to core dumps in order to see how device is getting crash and to develop an exploit we need core dumps. so we have to do the two things in order to get device fuzz ready first enable the core dump and then restart the webserver as we are fuzzing web application here.In embedded devices application,application logic are embedded inside the web-server for memory concerns. so below are the step by step instructions to do it.
- Enable core dump.
- echo -n '/tmp/core.%p' > /proc/sys/kernel/core_pattern
- Setiing ulimit to max
- ulimit -c 99999999999
- Now restart the webserver.
- pkill -9 boa
- generally it gets automatically started as there are watchdogs are running but in case if it now get started then we can manually start with device specific commands e.g in my case it was
- /userfs/bin/boa -c /boaroot -d &
This will enable core dump and make device fuzz ready.
While doing red team or bug bounty I generally get pissed of with authenticated exploits I mean why even if the Auth-RCE is there its useless because you cant demonstrate it. so my focus is more on discovering Unauthenticated Remote Code Execution, so I try to fuzz every parameter in login request and every unauthenticated page so if you got the real bug I mean RCE that to unauthenticated then it gives the hacker wala feeling so my focus is always on discovering Pre-Auth RCE.
So I intercepted the login request and setup my fuzz list in intruder and fired it. which looks like below.
|Request with Fuzz-list.|
And wait to finish it.
|Payload configuration and finished.|
Now the obvious thing which I expect is Crashes
UGhHHHH THose Offsets.
You Might get the crash but the first thing is to identify at which point it gets crash, So in our case here device was getting when the payload is set to 5000 A
|Crash at 5000 A|
As we can see here after sending A 5000 at password parameter its crashing the web server. so now we are sure that we got the crash its time to reproduce it multiple times to double ensure it.
D-Bug DeBug D-Bugger
so the next important task is how can we debug this initially it sounds very tough but later you get used to with it. So the approach here is we will install gdb server on device and then we connect our pwngdb client it. so the first step is to find the proper gdb server you can download the gdbserver for multiple architecture from below URL.
As we have full busybox now we can simply host the gdbserver to our web server and we can do the wget
|Downloading the gdb|
And then we have to attach the process and then connect our gdb client to gdbserver.
- get the pid with ps of boa
- ./gdbserver --attach 192.168.1.1:1337 1356 --> pid.
- gdb-multiarch ==> Start the gdb-client
- target remote 192.168.1.1:1337 ==> this will connect to gdbserver
- ir ==> to see the state of register
Reproducing the crash with debug enable.
as we learned to enabled the debug now follow the below steps
- Start boa and get the pid.
- attached the PID with gdbserver
- Connect system to device with gdb multi arch
- fire the crash
- see the states of register.
which looks like below.
|Boom BooM x41 everywhere|
Now we have to find the correct offsets so generate the pattern with msf and paste it as a payload and then fire the payload, again you have to see the register values and look for the offsets of the register values to identify the control over register.
As we can see here we have access of below registers at particular addresses
- T4 and T7 at 1000,1004
- T6 at 1024
- S0 to S3 at 1028 to 1044
- pc at 1044.
Once you have this much of data one can easily develop an simple POC exploit which looks like below.to demonstrate the control over register in order to achieve the code execution in MIPS we have to use some technique like ROP, but still below exploit is sufficient to demonstrate the power.
Hope you have enjoy the reading.