[Part 1] Hacking NETGEAR JWNR2010v5 Router - Authentication Bypass
[Part 2] Hacking NETGEAR JWNR2010v5 Router - Command Injection
It has been a long time since my last update so today I want to show you two vulnerabilities found while reversing the firmware from a NETGEAR router. The exploitation of these two vulnerabilities provides the attacker full remote unauthenticated root access to the device if it has WAN administration enabled.
First things first, the content you are about to read is intended as educative content, do not hack random thing out there, don't be stupid. Ok, let's start with this. In this case I analyzed the firmware 18.104.22.168 published on 05/11/2015 for the Netgear JWNR2010v5.
You can download the file here: http://www.downloads.netgear.com/files/GDC/JNR1010V2/ N150_N300_FW_V22.214.171.124_1.0.1.zip
From the binwalk output we know that the arch is MIPS and there is a SquashFS filesystem at 0x160000 which we extract using dd:
DECIMAL HEX DESCRIPTION ------------------------------------------------------------------------------------------------------------------- 60352 0xEBC0 U-Boot boot loader reference [...] 131072 0x20000 uImage header, header size: 64 bytes, header CRC: 0x23F4018D, created: Thu Nov 21 21:18:53 2013, image size: 1266253 bytes, Data Address: 0x80000000, Entry Point: 0x8000C2F0, data CRC: 0xE8A06868, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image" 131136 0x20040 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 4632092 bytes 1441792 0x160000 Squashfs filesystem, little endian, version 4.0, compression:lzma (non-standard type definition), size: 2376782 bytes, 1160 inodes, blocksize: 131072 bytes, created: Thu Nov 21 21:18:35 2013 [...] 4028341 0x3D77B5 End of Zip archive # dd if=N300.bin bs=1 of=N300.squashfs skip=1441792 2752512+0 records in 2752512+0 records out 2752512 bytes (2.8 MB) copied, 2.73591 s, 1.0 MB/s # file N300.squashfs N300.squashfs: Squashfs filesystem, little endian, version 4.0, 2376782 bytes, 1160 inodes, blocksize: 131072 bytes, created: Thu Nov 21 21:18:35 2013 # ./unsquashfs_all.sh N300.squashfs [...] created 850 files created 60 directories created 144 symlinks created 106 devices created 0 fifos File system sucessfully extracted!
I use to run a script that test every file in the webserver and returns the error code, so I did, and from this preliminary file access analysis I found that an unauthenticated user can access every static file located in the webroot which is interesting but not very useful, anyway reviewing the results of this test I found the tip of the iceberg. Every time I ran the script and reached one file the following files were available without authentication (Error 501 == 200):
501http://192.168.1.1:8080/401_access_denied.htm 501http://192.168.1.1:8080/401_recovery.htm 401http://192.168.1.1:8080/Add_WPS_Client.htm 200http://192.168.1.1:8080/advanced.js 401http://192.168.1.1:8080/adv_index.htm [...] 401http://192.168.1.1:8080/BAS_basictop.htm 200http://192.168.1.1:8080/bas_bpa.js 200http://192.168.1.1:8080/base.gif 401http://192.168.1.1:8080/BAS_ether_h.htm 401http://192.168.1.1:8080/BAS_ether.htm [...] 401http://192.168.1.1:8080/BRS_05_networkIssue.html 401http://192.168.1.1:8080/BRS_check_manulConfig.html 401http://192.168.1.1:8080/BRS_hijack_index.htm 401http://192.168.1.1:8080/BRS_hijack_success.htm 401http://192.168.1.1:8080/BRS_index.htm 501http://192.168.1.1:8080/BRS_netgear_success.html [From this point every 401 error becomes a 501] 501http://192.168.1.1:8080/BRS_plzWait.html 501http://192.168.1.1:8080/BRS_RUS_auto_account_input.html 501http://192.168.1.1:8080/BRS_RUS_auto_attention.html [...]
And even worse...when I ran the script again every file returned a 501 error, so by doing this I disabled the authentication for the router somehow and with this we reached the "IDA Time!". By analyzing the router behaviour we can see that the authentication is handled by the webserver binary, so we import it to IDA and search for our reference string ( BRS_netgear_success.html ) which returns an intermediate function between 'main' and other function that we called 'auth_req_check' because of a .htpasswd reference.
This intermediate function will be called 'url_handle' as we can see a clasic staircase pattern comparing the reveived URL with hardcoded strings using strstr() function and executing different actions. Now we identified and isolated the authentication and url handler functions, lets move to our suspicious string. As you can see in the following image if the url contains the string ( BRS_netgear_success.html ) it moves to an interesting piece of code which sets two variables in the nvram to 0 (need_not_login and start_in_blankstate)
With this in mind it's easy to understand what is this doing, wen we access BRS_netgear_success.html the router redirects to NETGEAR webpage just to check whether we have internet access or not, and allows the user to access the router without credentials just for change the administrative password...but...this should be only allowed the first time the router is connected which is not the case... Finally lets confirm our assumptions checking where the bypass is done. For this, we have to move to the 'auth_req_check' function that we named previously ( offset 00403858 if you want to check) and read from the beginning where the function checks the existence of the .httpasswd file. If yes, we find a reference to start_in_blankstate where it's compared to be different to 1 and if yes the login is bypassed:
With the we confirmed that if start_in_blanckstate is 0 the .htpasswd is disabled and we have free access to the admin panel of the router.
So in short, if we hit this URL http://[IP_ROUTER]:[PORT]/BRS_netgear_success.html the login for every page in the router is temporary disabled.
I could confirm that the following models are vulnerable to this: NETGEAR_JNR1010v2, NETGEAR_JNR3000, NETGEAR_JWNR2000v5, NETGEAR_JWNR2010v5, NETGEAR_N300, NETGEAR_R3250, NETGEAR_WNR2020, NETGEAR_WNR614, NETGEAR_WNR618
But this is only the beginning and we want to get unauthenticated root access to the router.
In the following post I explain a vulnerability that affects just these two models (JWNR2010v5 and JWNR2000v5) that allows us to fully compromise the router and also you can find a PoC to test with your own router.