Almost ten years ago Firesheep made the news. Security people had known for years the danger of public WiFi-networks, but it was not until someone made a user-friendly Firefox extension out of the idea until it really got people’s attention. Since then a lot has happened to the web, so would something like that still be possible?
TL;DR; MITM is less of a problem today due to HTTPS. However, using CORS, postMessage, and other cool stuff it is sometimes possible to bypass HTTPS. This is the fault of the website owners, but the victim are the users.
Firesheep was top of the mind just a few years ago. Websites, and in this case primary Facebook, and not yet started using HTTPS per default. The drastic increase of mobile devices, both laptops and phones, made it more and more common to connect to untrusted WiFi-networks.
Today, eight years later, this is actually less of a problem. This is due to the wide adoption of HTTPS, lots of traffic being encrypted. Just last week WIRED published an article called You Know What? Go Ahead and Use the Hotel Wi-Fi. The traffic from your devices are now encrypted, and even if someone MITM you there is not too much to be done. And it is definitely true, a lot has changed since MITM at a hotel or coffee shop was the very first you would mention when talking about security.
As you travel this holiday season, bouncing from airport to airplane to hotel, you’ll likely find yourself facing a familiar quandary: Do I really trust this random public Wi-Fi network? As recently as a couple of years ago, the answer was almost certainly a resounding no. But in the year of our lord 2018? Friend, go for it.
However, there still are a lot of bad stuff that can happen if someone MITM regardless of encryption. There are several angles to approach the topic from. This article will focus on how modern web techniques can still do harm, and how a website owner could prevent it.
(The WIRED article still has a valid point, but there is space for a technical discussion on it as well.)
Attack scenario the rest of the article will be based on
You are spending the night at a hotel and have just connected your device to the hotel WiFi. As you are on an untrusted network, you are smart enough to not browse anything sensitive.
However, you are using the same browser session as usual. Out of convenience, people never log out from Facebook or their work email.
HSTS and cookie flags
Need to start with some basic information about HSTS.
HSTS is an HTTP-header that instructs the browser that in the future it should only try to load that page over HTTPS. From the first time the browser visits a site with this header, it will add the domain to a list and remember it for as long as specified in the header. Even if I explicitly wrote
http:// the web browser would directly send the request over HTTPS anyway.
It is also possible to add a flag to get the header preloaded. When a web browser gets updated/downloaded, a list of preloaded domains is included. The web browser will refuse to ever send HTTP-traffic to those domains, even when the user goes to it for the very first time.
Another important feature of HSTS is a flag called includeSubDomains. If
https://example.com includes this header, the web browser will refuse to send any unencrypted traffic to
http://foo.example.com as well.
The HSTS-header can only be set on HTTPS-requests. According to specifications, this header should be useless on HTTP-requests (not tested enough browsers in practice to say for sure). This leads to a common problem when people are doing redirects in the following order:
http://example.com > http://www.example.com > https://www.example.com
As the first HTTPS-request would go to
www. the includeSubDomains-flag does not work, as that must be set on the apex domain.
Lastly, which also needs to be mentioned here in the intro is the secure-flag. This is a flag that is set on cookies when creating them. When this flag is set, the cookie will never be sent over HTTP. If a request is made to
http://example.com it would look like the user has no saved cookies.
We have covered common CORS misconfigurations here before. I would recommend reading that article first if you have not already done so.
The simplest attack is when HSTS is not used at all. Assuming CORS allows it,
http://example.com can make a request to
https://example.com and read the data. This would be possible in a MITM-scenario as the request making the request is hosted over HTTP. As the actual request would be sent over HTTPS, even cookies with the secure-flag are sent with it.
http://foobar.example.com that makes a request to
https://example.com. In a MITM-scenario, an attacker can make up any subdomain at their will. This is extra common when the main application is hosted on www. due to the redirect issue explained under HSTS.
An interesting attack vector is when HSTS is used, but CORS support multiple domains. Using a real example, CORS on
periscope.tv accept both
*.twitter.com over both HTTP and HTTPS. As soon as one would log in to periscope.tv the HSTS will make sure no future requests are sent over HTTP to that domain. However, chances would be pretty high that the victim has never visited
*.pscp.tv before and in a MITM-scenario an attacker would be able to put up a fake page hosted on HTTP there and through that send requests to
periscope.tv. In this scenario, such an attack would be stopped because all the HSTS-policies of all these domains are preloaded.
As we have written about before, it is very important to check the origin of messages when using postMessage. However, it is quite common that those checks only check that the origin ends with something specific and thereby allow any subdomain. This means a total lack of check protocol. An HTTP-page on any subdomain would be able to send messages to the main application.
There are also regex-based origin checks out there that intentionally allow both HTTP and HTTPS, even though the web application is supposed to only be available over HTTPS. With this should also be noted that there are several protocols that actually could host web content, such as FTP. It is therefore important to make sure to whitelist HTTPS, rather than blacklisting HTTP. Example of what I assume is something related: https://hackerone.com/reports/210654
As for the combination with HSTS, the same principles goes as for the CORS issue.
WebSocket actually share cookies in the handshake request and therefore would require an origin-check in a similar fashion as what is done with CORS request. This is only important if the application actually cares about cookie-data, so not always applicable.
There might be similar ways or technologies out there that can be misused in a similar fashion. And if there are not today, there will soon be. Assuming MITM is within your threat model, these are questions that should not be ignored.
The first step is to actually start with using HSTS as many do not today. On a website that already serves everything over HTTPS, there are no issues in doing this. And when you have implemented this and made sure it works, add the flag about getting it preloaded.
If possible, make the header include the includeSubDomains-header. However, this requires all the subdomains to also serve all traffic over HTTPS, something that depending on circumstances can be a bit of a struggle.
Make sure that CORS only accept HTTPS-requests. As the most common solution is to reflect the origin assuming it matches a pattern, this also needs to check that it begins with
postMessage and WebSocket
Very similar to CORS: make sure that there is an origin-check and that checks the protocol and not only the hostname.
Prior to writing this post I was in contact with security people from a few major websites that are having these issues. While many do care, there are several considering this an acceptable risk. They believe it to be unlikely that a victim gets MITM or similar reasoning. So while it should be to the responsibility of the site owner to get it fixed, there are certainly reasons for a user to care as well.
- The very first step would be to install HTTPS Everywhere. It is a browser plugin doing something similar to HSTS, but on the client.
- The second recommendation would simply be to not use public WiFi. What also has changed since the time of Firesheep is the pricing of mobile data. Many people that regularly connect to open networks could just as well connect through their phone.
- When that is not applicable, the second best recommendation is to use a VPN. However, it should be mentioned that this is not a bulletproof strategy either. As many public hotspots have some kind of login page when you connect to them, you actually have to be connected to the network for a short while without traffic going through the VPN. In this time period, it would be possible to force your device to make requests that exploit techniques described earlier.
To end everything with a quote from the WIRED article again. Keep in mind doing a risk analysis of your own situation and act thereafter.
[..] Likewise, if you’re a high-value target of a sophisticated nation state—look at you!—stay off of public Wi-Fi at all costs. (Also, you’ve probably already been hacked some other way, sorry.)
But for the rest of us? You’re probably OK. [..]