# Multiple Vulnerabilities in Wavlink Router leads to Unauthenticated RCE -CVE-2020-10971 and CVE-2020-10972
* Post author By [James Clee](https://james-clee.com/author/jamesclee19gmailcom/)
* Post date [April 18, 2020](https://james-clee.com/2020/04/18/multiple-wavlink-vulnerabilities/)
* [No Comments on Multiple Vulnerabilities in Wavlink Router leads to Unauthenticated RCE - CVE-2020-10971 and CVE-2020-10972](https://james-clee.com/2020/04/18/multiple-wavlink-vulnerabilities/#respond)
With everyday household items becoming "smart" and connected to the internet,
I was interested in seeing how much effort companies were putting into
security. I decided it would be a great hobby to buy cheap Chinese technology
off of Amazon and see what I could find out.
After searching for routers, I found one from a company called Wavlink that
was only $30 off of [Amazon](https://www.amazon.com/WAVLINK-Extender-
Coverage-1200Mbps-
Wireless/dp/B07THZ9LBK/ref=sr_1_4?dchild=1&keywords=wavlink+router&qid=1587328486&sr=8-).
The Wavlink WL-WN530HG4 is an Amazon's Choice Router with "WPA/WPA2 PSK Mixed
security and industry level password encryption". Additionally, they say "We
are fully confident in the design and durability of our products. If you have
any issues, please do not hesitate to contact us anytime, night or day : -) ".
While the WiFi password might have "industry level password encryption" it's
like putting a very secure padlock on a two foot high fence and the key is
under the pot right next to it. But first, lets talk about how I came to that
conclusion.
Initially setting up the router was one of the most difficult parts of
achieving RCE. Maybe it has to do with my convoluted internet setup in my room
at home (Modem -> WiFi Router Downstairs -> Powerline Ethernet Adapter ->
Switch in my room -> Wavlink Router) but it kept redirecting me to a page that
was half in Chinese telling me I wasn't connecting directly to the router,
even though I was going straight to its IP address. Either way, I did
eventually get it set up and started exploring.
I was running Burp while I was doing the initial setup, and one of the things
I noticed right away was that after I logged in and was viewing the home page,
it looked like calls were being automatically made to a few endpoints to
update stats.

Automatic requests while logged into the router
The endpoints all followed the format "live_(string).shtml" and had what
appeared to be some kind of session id called "r" that was being sent with the
request. Just for fun, I tried going directly to one of the pages without the
"r" parameter and I was still able to view the response. Even after I logged
out and could not get to the main page, the "live_(string).shtml" endpoints
were all still reachable - it appeared no authentication or session ID was
required to get there.

live_speed.shtml returns incormation without potential ID as parameter
Now that I had a basic feel for how the router worked, I decided to take it
apart. Serial pins is something that has interested me ever since I first
heard about them. The idea of a free backdoor is just too juicey for me to
pass up. Plus, finding a way to get into a device remotely is much easier when
you start from the inside.
Turns out, trying to take the router apart was the second hardest part about
achieving RCE - there was a lot of little plastic clips holding the top on,
and I missed two screws hidden under a label which was preventing me from
making any significant progress. After 15 minutes of prying I realized what I
had missed, and I finally had my first look at the board.

The router before I tried to demolish it

It took me way to long to find these bad boys

Finally got the lid off. Immediately noticed the groups of pins at the top
I had my multi-meter and jtagulator at the ready, but fortunately Wavlink was
kind enough to label the serial pins for me.

TX, RX, GND, and VCC identified in 2 seconds flat
I soldered on a couple of wires, and using my Attify badge and this [handy
baudrate
script](https://github.com/devttys0/baudrate/blob/master/baudrate.py), I was
able to establish a serial connection with minicom.

RX TX and GND connected to the Attify Badge and then to my PC

Using the baudrate script - activity seen right away, cleartext identifies baudrate as 57600

Minicom session gets a prompt
At the end of the bootup I was presented with a "WAVLINK login:" prompt. I
tried using several normal usernames like root or admin with the password I
set in the gui, but nothing worked. I was a bit dissapointed, but after I
looked back through the boot logs I found this line about a password change
that always appeared:

First mention of this user - no username is entered in the GUI
I decided to try logging in with "admin2860" and the gui password and boom - I
was in. It appeared to have a version of BusyBox running on the router. The
serial connection was a success, but super annoying to use because whenever
you try and type or view a file it decides to spit out a log for some activity
happening on the router. Fortunately, it has a built in telnet binary. After
starting it, i was able to connect on a port of my choosing with admin2860 and
not worry about logs screwing up my view.

Successful login via serial connection
Now that I had a solid connection, I started to explore what webpages were
available to the end user. The web directory appeared to be
/etc_ro/lighttpd/www/ and listed way more webpages then I had uncovered in my
manual exploration. Besides the first few endpoints that were automatically
hit, I found tons of "live_(string).shtml" pages that did not require any sort
of authentication to get to. And this is where the fun begins.
One of the first pages I checked in the GUI had the below interface. It
appeared to be a way to pause some functionality for testing purposes - and of
course, no authentication is required to get to it.

It did have an input for your password, so I thought that maybe there was some
security on this thing after all. I tried to compare the authentication method
with the main login page and boy was I surprised by what I found.

Basic string comparison for the password - admpass is the input text box
Instead of sending my password off to be verified on the back end, it appeared
to be checked against a local variable. Curious as to how this was done, I did
a quick search for "password" and I literally laughed out loud as to what I
found.

Input password compared against plaintext variable
Low and behold, there was my super secret password in plain text, with the
admin username in plain text, on a page that requires no authentication of any
kind to view. Considering how they already have a built out authentication
process used for other pages, its very curious that a developer would go out
of their way to set up something different for this one page in such a
blatantly insecure manner. Thanks to my handy backdoor, I was able to find
that a command is executed on the backend to populate that syspasswd variable
every time this page is loaded - that way in case you change the password, you
don't have to worry about this page being out of date.

Running the command myself returns the current password, in plaintext
So what does that get us from the perspective of a remote attacker? We have
the ability to get the current admin credentials, and we can get a shell if
the telnet binary is started. However, most remote attackers wont be able to
solder on any wires, so I wasn't going to stop there.
Going through the rest of the pages in the www directory, there is another web
page that provides this interface:

A built in GUI for command
execution as root - could it be that easy?
Obviously this immediately grabbed my attention. I tried a simple "ls" command
and the page redirected me to /cgi-bin/(null) and errored out. This was a
disappointing result, but when I copy-pasted the address back in to relook at
it, I found that the command had appeared to actually execute and it returned
the results.

The output of my sample ls command
It appears that the command is executed as the admin2860 user in the
/etc_ro/lighttpd/www/cgi-bin directory, and although the redirect feature is
broken the command is still executed. I was pleasantly surprised that this
page was not accessible without being logged in. Of course, since the admin
credentials are already exposed this doesn't buy you much security - by just
going to one other page, you can find the info to log in and execute commands.
Additionally, I stumbled across an interesting fact. While you cannot access
the web page for the Command Execution interface, you can still make a POST
request to adm.cgi. If it's in the proper format, and a user is logged in,
then the command is executed. While the router appears to do some verification
to ensure that someone is authenticated at that time, it makes no discernible
effort to verify that the POST request actually came from the user that is
authenticated. So even if the endpoint with the plaintext credentials is
removed, an attacker could just make a loop of post requests to adm.cgi and as
soon as a user logged in they would achieve command execution.
In conclusion, a remote attacker can achieve RCE via a POST request to
adm.cgi. There are several conditions required, including proper parameters
and an active session. However, these conditions can all be met without any
initial authentication required thanks to several specific exposed
"live_(string).shtml" endpoints - so an attacker with the right background
information about the device could achieve RCE fairly easily.
I did not go very in depth about maintaining persistence on the device outside
of the initial exploit chain. I tried creating additional users but they
appear to be removed on boot - I believe I could circumvent this with enough
time, but due to the already exposed flaws I didn't feel it was worthwhile
spending the time on it.
I attempted multiple times to contact Wavlink about the issues I found via
several different support contacts on their site but I was never able to get a
response from them. After weeks of no communication, I submitted a report to
Mitre and CVE-2020-10971 and CVE-2020-10972 were created, covering this
device.
Timeline:
2/19/2020 - Initial discovery and notification
2/29/2020 - Follow up notification after no response
3/23/2020 - Follow up notification after no response indicating plans to
submit for CVE
4/3/2020 - Additional communication attempts failed to get response, CVE
request submitted
5/7/2020 - CVE published
6/30/2020 - Additional details published
暂无评论