Debunking Google’s HSTS claims
Nov 22, 2013**Disclaimer**: This post was published before I started working at EFF, hence some stylistic mistakes (calling it “the EFF” rather than just “EFF”) are excusable and left uncorrected. 🙂
Two days ago, the EFF published a report tiled, “Encrypt the Web Report: Who’s Doing What.” The report included a chart that rated several large web companies on how well they were protecting user privacy via recommended encryption practices for data in transit. The five ranking categories were basic HTTPS support for web services, encryption of data between data centers, STARTTLS for opportunistic email encryption, support for SSL with perfect forward secrecy, and support for HTTP Strict Transport Security (HSTS). It looks like this:
By most measures, this is an amazing chart: it’s easy to understand, seems technically correct, and is tailored to address the public’s concerns about what companies are doing to protect people from the NSA. On the other hand, I don’t like it much. Here’s why:
The first problem with the report is that it inadequately explains the basis for each score. For instance, what does a green check in the “HTTPS” category mean? Does it mean that the company is encrypting all web traffic, or just web traffic for logins and sensitive information? Sonic.net certainly got a green check in that category, yet you can check that going to http://sonic.net doesn’t even redirect you to HTTPS. Amazon got a red square that says “limited”, but they seem to encrypt login and payment credentials just fine.
The second problem is that the report lacks transparency on how its data was acquired. It states, “The information in this chart comes from several sources; the companies who responded to our survey questions; information we have determined by independently examining the listed websites and services and published reports.” Does that mean the EFF sent a survey to a bunch of companies that asked them to check which boxes they thought that they fulfilled? Could we at least see the survey? Also, was each claim independently verified, or did the EFF just trust the companies that responded to the survey?
I looked at the chart for a while, re-read the text a couple times, and remained unconvinced that I should go ahead and share it with all my friends. After all, there is no greater crime than encouraging ordinary people to believe whatever large companies claim about their security practices. That just leads to less autonomy for the average user and more headaches for the average security engineer. So I decided to take a look at the HSTS category to see whether I could verify the chart myself.
For those who are unfamiliar, when a website says that they support HSTS, they generally mean that they send a special “Strict-Transport Security” header with all HTTPS responses. This header tells your browser to only contact the website over HTTPS (a secure, encrypted protocol) for a certain length of time, preferably on the order of weeks or months. This is better than simply redirecting a user to HTTPS when they try to contact the site over HTTP 1, because that initial HTTP request can get intercepted by a malicious attacker. By refusing to send the HTTP request at all and only sending the HTTPS version of it, your browser protects you from someone sending you forged HTTPS data after they’ve intercepted the HTTP request.
1 HTTP traffic can be trivially read by anyone who intercepts those packets, so you should watch out for passwords, cookies, and other sensitive data sent over HTTP. I wrote a post a while back showing how easy it is to sniff HTTP traffic with your laptop.
(HSTS is a good idea, and all servers that support HTTPS should implement it.
If you decide to stop supporting HTTPS, you can just send an HSTS header with “max-age=0.”)
But HSTS still has a problem, which is that the first time a user ever contacts a website, they’ll most likely do it over HTTP since they haven’t received the HSTS header from the site yet! The Chromium browser tried to solve this problem by coming with an HSTS Preload List, which is an ever-growing preloaded list of sites that want users to contact them over HTTPS the first time. Firefox, Chrome, and Chromium all come shipped with this list. (Fun note: HTTPS Everywhere, the browser extension by the EFF that I worked on, is basically a gigantic HSTS preload list of 7000+ domains. The difference is that the HTTPS Everywhere list doesn’t come with every browser, since it’s much less stable, so you have to install it as an extension.)
Anyway, let’s see if Google’s main search supports HSTS. To check, open up a browser and type in “http://google.com.” If it supports HSTS, the HTTP request never returns a status code. If it doesn’t support HSTS, the HTTP request returns a 302-redirect to HTTPS.
Results, examined in Firefox 25 with Firebug:
Nope! As you can see, the HTTP request completes. As it does that, it leaks our search query (“how to use tor”) and some of our preference cookies to the world.
The request then 302-redirects to HTTPS, as expected, but that HTTPS request doesn’t contain an HSTS header at all. So there’s no way that Google main search supports HSTS, at least in Firefox.
I was puzzled. Why would Google refuse to send the HSTS header, even though they support HTTPS pretty much everywhere, definitely on their main site? I did a bit more searching and concluded that it was because they deliberately send ad clicks over plain HTTP.
To prove this to yourself, do a Google search that returns some ads: for instance, “where to buy ukuleles.” If you open up Firebug’s page inspector and look at the link for the ad, which supposedly goes to a ukulele retail site, you’ll see a secret hidden link that you hit when you click on the ad! That link goes to “http://google.com/aclk?some_parameters=etc,” and you can conclude that Google wants you to click on that HTTP link because they put it in the DOM exactly where you’d want to click on it anyway.
Let’s click on that ukulele link. Yep, we end up redirected to http://googleadservices.com (plain HTTP again), which leaks our referer. That means the site that posted the ad as well as the NSA and anyone sniffing traffic at your local coffeeshop can see what ads you’re looking at and what you were searching for when you clicked on them.
This is presumably the reason that Google.com doesn’t send the HSTS header and isn’t on the HSTS preload list. But wait, there’s plenty of Google domains that are in fact on the preload list, like mail.google.com, encrypted.google.com, accounts.google.com, security.google.com, and wallet.google.com. Don’t they send the HSTS header?
I checked in Firefox, and none of them did except for accounts.google.com. The rest all 302-redirect to HTTPS, just like any HTTPS site that doesn’t support HSTS.
Then I did a bit more reading and found out that HSTS preloads were implemented such that Firefox ignored any site on the preload list that didn’t send a valid HSTS header with an expiration time greater than 18 weeks. This seems like a valid design choice. Why would a site want to be on the preload list but not support HSTS at all for people with non-Firefox/Chrome/Chromium browsers? And if they don’t send the header in the first place, how do we know when the site stops supporting HSTS?
Given that Google doesn’t really provide the benefits of HSTS to any browsers except Chrom{e, ium}, it’s hard to argue that it deserves the green check mark in the HSTS category. The moral of the story is that the EFF is awesome, but having a healthy mistrust of what companies claim is even more awesome.
=====
[IMPORTANT EDIT (11/23/13): The following originally appeared in this post, but I’ve removed it because it turns out I was accidentally using a version of Chrome that didn’t have the HSTS preloads that I was testing for anyway. Thanks to Chris Palmer for pointing out that Chrome 23 is a year old at this point, and apologies to everyone for my error.]
Alright, so I had to also check whether Chrome respected the preload list even for sites that didn’t send the header. To be extra careful, I did this by packet-sniffing my laptop’s traffic on port 80 (HTTP) with tshark rather than examining requests with Chrome developer tools. The relevant command on a wifi network, for anyone who’s curious, is:
tshark -p port 80 -i wlan0 -T fields -e http.request.method -e http.request.full_uri -e http.user_agent -e http.cookie -e http.referer -e http.set-cookie -e http.location -E separator=, -E quote=d
Let’s try http://wallet.google.com. Yep, we leak HTTP traffic. (It then redirects to https://accounts.google.com because I haven’t logged in to Wallet yet.)
How about http://security.google.com? Yep, we leak HTTP traffic there too.