[Part 1] Hacking NETGEAR JWNR2010v5 Router - Authentication Bypass
[Part 2] Hacking NETGEAR JWNR2010v5 Router - Command Injection
We already saw how to bypass the authentication so in this post I want to focus in the compromise of the underlying system. In order to do this we have to understend how the router works internally and the management of the administration interface.
Checking the filesystem we got in the previous post I found that everything is handled by just one cgi called setup.cgi:
# ls -l | grep cgi
lrwxrwxrwx 1 root root 18 Jul 28 07:51 conf -> restore_config.cgi
lrwxrwxrwx 1 root root 9 Jul 28 07:51 htpwd_recovery.cgi -> setup.cgi
-rwxr-xr-x 1 root root 59784 Apr 1 01:34 restore_config.cgi
-rwxr-xr-x 1 root root 613588 Apr 1 01:34 setup.cgi
-rwxr-xr-x 1 root root 277152 Apr 1 01:34 setupwizard.cgi
lrwxrwxrwx 1 root root 9 Jul 28 07:51 upgrade_flash.cgi -> setup.cgi
One of the most common vulnerabilities we can see on SOHO routers are command injection through bad implemented functions, so my priority is to find where a command is executed to against the system and that allows me to control the input. For this I opened setup.cgi in IDA and search for keywords, in this case '/bin':
The ping command caught my attention as it meets both conditions. In this case the webpage that handles this is diag.htm which allows the user to perform different tests to validate the internet connectivity.
By opening diag.htm and reading the source code we find the first interesting thing. Input data is validated client side, so just changing return ping_ck() by return true or modifying the POST request we can send our crafted data.
As you can see above we tried to inject a command appending ';' to the IP address but the command never reaches the server. It's filtering it server side, so let's take a look at the cgi:
As you can see, it searches for a semicolon in the request and if exists the command is never executed...but..what happens here? It only filters the semicolon so if we replace it with '&&' we bypass the check and the command is successfuly executed...or it should...
If we run the command against the system we receive a 403 error but I noticed that setup.cgi gets a GET numeric parameter as follows...setup.cgi?id=0000000 So let's move again to IDA and search for 'id=' string:
First main() search for POST parameters and environment variables, if not found seek for GET parameters. In case it finds 'id' runs strtol() and if succeed extract the content of /tmp/SessionFile and compares against the id parameter where if doesn't match returns the 403 error.
Finally we know that we need to sign the request with this parameter in order to run the command, so we use the auth bypass vulnerability from the previous post to access the web interface, scrap the source code to extract a valid sessionid before it changes, craft the injection and returns the response.
Here is a script to do this:
And finally we got the expected result in the response after running a 'pwd' command:
Unlike the previous vulnerability this only affects to two models JWNR2000v5 and JWNR2010v5.
In the following link you can find a PoC exploit:
https://github.com/remot3/exploit-POC/blob/master/NETGEAR_JWNR2010v5.py