Hello my fellow hackers! Recently there was a vulnerability discovered in Netgear R7000 routers. This vulnerability allows for the attacker to inject commands into the router through HTTP requests with malformed URIs.
As hackers, it’s important that we keep up with these vulnerabilities so that we never miss a chance to use them. Keeping up with security bulletins and vulnerabilities disclosures are very important parts of being a hacker, as they let us utilize the latest exploits instead of recycling years-old exploits again and again.
To demonstrate and practice this pseudo digital literacy, we’ll be building our very own exploit script for this vulnerability! We’ll start by dissecting the information we have about the vulnerability, then we’ll talk about (and build) our exploit. So, let’s get started!
Dissecting the Vulnerability
To start, let’s go over the vulnerability (which can be found here). Let’s look at the information, then we’ll discuss it:
We can see here that this vulnerability is pretty simple. By passing a semi-colon and a command into the URI, we can inject it into the router. It may seem simple, but we can still learn quite a bit by building our own exploit. In our exploit, we’re going to make HTTP requests with the malformed URI, which will trigger the telnet service on the router. This service will not have any authentication, so we will have control over the router! Now that we know how this vulnerability works, let’s get started building our exploit.
Building the Exploit
Step 1: Imports and Input
Before we can do anything in our script, we need to import the modules we need and take the input from the user. Let’s see the code, and we’ll discuss it after:
We start by importing three modules. The socket module will be used to check for the correct circumstances for the exploit to take place. If port 80 (the web interface) is open, and port 23 (the telnet port) is closed, then the circumstances are correct. The sys modules will simply be used to take input and exit the script when needed. The requests module is for making and using HTTP requests. This is what we’ll be using to trigger the vulnerability with the malformed URI.
After we import these modules, we check the length of sys.argv. Sys.argv is an automatically generated list of all the arguments that were given to the script. In this case, we’re only going to taking one argument, the target. So, if the length of sys.argv is not equal to 2, the arguments are incorrect (the script name counts as the first argument). After we check this, we assign the first argument to the variable named host.
Step 2: Checking for the Vulnerability
Now that we have our modules imported and our input taken, we need to see if the vulnerability is even available for exploitation. We can do this by checking if we can establish connections to the ports effected by the exploit. We’ll discuss this after we look at the code:
This function may be simple, but it’s very important. We start by making a socket and attempting to connect to port 80. We store this result in a variable and move on. We then create a second socket and attempt to connect to port 23, we also store this in a variable and move on. We then close both our sockets and we move on to evaluating our results. If we can connect to port 80, but not 23, the circumstances for the exploit are correct (The web interface is enabled, but telnet is not (we’re going to enable it)). If this isn’t met, we raise and exception, which is then caught and dealt with (this method isn’t really necessary, but it saves a few lines of code).
Step 3: Build the Exploit Function
Now that we know the exploit circumstances are correct, we need to build the function that will exploit the vulnerability. This is actually the simplest function we’ll be building. Let’s take a look at it:
This function is extremely simple. We just make an HTTP GET request to the targets address, and we pass the malformed URI. The command we’re executing is telnetd. This will start the telnet service on port 23 with no authentication. On to the next function!
Step 4: Build the Verification Function
Now that we have a function to exploit the vulnerability, we need one to make sure it worked! This will be a lot like our function to check for the vulnerability, but with a small twist:
In this final function, we make a single socket, and attempt a connection to the telnet port (port 23). We then close this socket and evaluate our result. If you remember from out checkVuln() function, the telnet port was closed. But now that we’ve sent our exploit, we can check again and it should be open. This function isn’t really 100% necessary, but it makes the attackers job easier.
Once we’ve finished all our functions, we simple call them in the order that we made them. Now that our exploit is complete (available here), we can test it out!
Testing the Exploit
To start, we’re going to be attacking an R7000 router that I have set up in my lab. Let’s perform a quick nmap scan of the target just to prove that everything is in order before we launch our attack:
We can see from the above nmap scan that port 80 is open, but port 23 is not (this will change very soon). Now that we have everything ready to rock, we can fire our exploit! We need to make it executable with the chmod command, then we can launch it:
By reading the output from our exploit, it seems that everything worked! Let’s launch another nmap scan just to see the change in open ports:
We can see by the output of our second nmap scan, that the telnet port has mysteriously opened. Let’s try to connect to is using telnet to see if it really worked:
There we have it, our exploit worked! We were able to make an HTTP GET request with a malformed URI to inject a command that enabled the telenet service with no authentication! We are now in control of this router.
This article is more than just a tutorial, it’s a proof of concept that by building something ourselves, we end up gaining a deeper understanding of how the technologies work. It’s one thing to know if an exploit works, but it’s much more important to know how an exploit works. I hope we successfully demonstrated that here.