Reversing IOT: Part 1


Hello, it’s been a while since my last post, but I’m here now to show you some basic reverse engineering tips for some IOT devices, I mean with this post I’m starting a series of reverse engineering on IOT devices 👨‍💻.


Well I cant disclose now the device tested and the vendor, so let’s say we are testing some Industrial LTE 4G router.

First I’ve downloaded the firmware from the vendor web page, and extracted the filesystem using binwalk:

xpl0ited1@freedom?$ binwalk -e firmware.bin

Then I started to look for some common .cgi endpoints like web.cgi, this to check if there is some way to bypass the authentication schema. I noticed that every time the device checks if the user is logged in, it does it by using the ICOS_CheckPrivilege function:

img_27.png

Also I saw that the ICOS_CheckPrivilege function also is used to check the user privileges, I mean if the user is admin, guest, etc. That kind of check is made by passing the result of the ICOS_CheckPrivilege function to the address stored at var_1c, and then checking that address with the level2str function:

img.png

Inside the level2str function there is some kind of switch/case sentence that checks if the value stored at the address on var_1c is 1,2,3,4 or 5. By this way the function returns the user level:

img_1.png

With all that in mind my question was “how does the ICOS_CheckPrivilege function calculates sets the user level and why?”. Here is how the ICOS_CheckPrivilege function looks like:

img_4.png

When looking at the code of the function, I saw that the crypt function is used:

img_5.png

This function “is the password encryption function. It is based on the Data Encryption Standard algorithm with variations intended (among other things) to discourage use of hardware implementations of a key search.”, and there is a paramater that is used for salting the key:

img_7.png

So for now I have that the data_4bef464c data reference is the salt for arg2 or the password input:

img_28.png

When checking at the address of the data reference I’ve got that the salt is just $1$ 🤦:

img_6.png

With all that in mind I made a few changes to the code of the function, modifying some variable names:

img_8.png

By other hand, there is a string comparison before comparing the password. At this comparison some value at R4 register is compared with the arg1, so I could guess that is the username, right?:

img_9.png

While examining the whole comparison code block, I noticed that is inside a do/while loop that increments by 1 the value of the R5 register every time until is 4, this remind the switch/case sentence, btw if the register is 4 it skips to the next line that check if the username is the same at the data_4bef4650 data reference, which is iwu@fbt&ND:

img_10.png img_12.png

This is how the level2str function looks like in Ghidra, as you can see if param1 (var_1c) is 4 it does nothing, and if it is 5 the user level returned is system:

img_11.png

So basically if the username is iwu@fbt&ND we are system:

img_13.png

But now what is the password for that user?, the password is stored at the var_84 pointer:

img_14.png

I renamed the var_84 variable to system_pass_addr, and if we look at the beggining of the function we could see the address were the password is stored in the stack:

img_15.png

So when looking at the stack we now have the address where the data reference of the system password is:

img_16.png

img_17.png

After cracking the password with hashcat I got the system user password:

img_18.png

Now, looking in Shodan for some exposed devices I could saw that there a few:

img_19.png

When browsing in some of the exposed devices I got this initial web page that shows me as guest:

img_20.png

Then I’ve logged in and had access to restricted functionalities:

img_22.png

img_23.png

img_24.png

img_25.png

And of course there is and RCE 🏴‍☠️ that I’ve already reported to mitre, and the best of all is fully unauthenticated, I’ve just found it by exploring as authenticated user the device portal, but it is also leaked in some JS files:

img_26.png


And that’s all folks, thanks for reading, and I will post a second part of the full RCE when the vendor release a patch. Cheers!!! 🦜

🏴‍☠️ 🏴‍☠️ 🏴‍☠️ 🏴‍☠️ 🏴‍☠️