Bypassing HSTS or HPKP in Chrome is a badidea

I saw some research published at BlackHat EU recently that detailed various ways to bypass both HSTS and HPKP in a variety of mainstream browsers. It was a novel technique and seems like a viable attack vector to bypass them, which is a big problem because both HSTS and HPKP offer serious protection. There is however another way that users can bypass these mechanisms quite easily.


HSTS and HPKP

First of all we have HTTP Strict Transport Security which is a highly valuable mechanism for making sure that connections to a site are always secure. You can read my introduction to HSTS, further details on HSTS Preloading and my HSTS Cheat Sheet if you want more info, but trust me, it's important! The TLDR; is that it stops users from clicking through security warnings in the browser and forces the browser to use HTTPS for secure communications on all communications, no exceptions. HTTP Public Key Pinning is another powerful security mechanism that I've talked about extensively in my introduction to HPKP and the HPKP toolset I built to help people deploy HPKP. For better or worse though, HPKP is being abandoned by Chrome and not long back I wrote about why I was giving up on HPKP and shortly after that Chrome happened to announce they were deprecating HPKP. Whilst HPKP is losing popularity, especially in the face of CAA and CT, HSTS is an absolute requirement for any sites that deploy HTTPS, without doubt.


Protecting the user

One of the major benefits of HSTS that I mentioned above is that the user can't click through browser warnings related to problems with a secure connection. We've probably all seen one before, most likely caused by a WiFi network with a crappy captive portal, but they tell us the same thing, the connection is not secure and the reason why.


hsts-fail


The one above is me trying to proxy traffic through Fiddler without installing the root cert and the next one is my intentionally bricked hpkp.scotthelme.co.uk subdomain.


hpkp-fail


Historically it used to be a simple case of expanding the advanced section out and clicking right through the error message without knowing what it really meant. HSTS stops that and instead you get no option to bypass the message, it's a fatal error message. If there's a problem with HTTPS we really shouldn't be clicking through that and using the connection in a broken state, it's kind of the point of HTTPS. Because I use HSTS on my blog, and all of my other sites, you can't click through the warning.


advanced


This is where things take a turn for the worse and it's something that's been around for quite a while. When I first saw the title of the research published at BlackHat I thought we were going to see what I'm about to talk about covered at the conference. To my surprise we didn't but we were presented with the awesome research they'd done on other methods.


You can actually bypass those warnings

Yes, it pains me to say it, but you can actually bypass the protection of HSTS and HPKP in Chrome with basically no effort, here it is:


hsts


No, there isn't any trickery there, I haven't done any photoshop work and there's nothing happening in the background either. When viewing a HSTS or HPKP error page in Chrome, or any HTTPS related error you want to click through, like the one shown above, you can simply type the letters badidea on your keyboard and Chrome will bypass the warning and load the site. If you want to try this out I have a subdomain with a self-signed certificate on it that you can test it on: https://self-signed.scotthelme.co.uk/

To clear a few things up, yes, I realise that the user is intentionally compromising themselves if they do this and yes an attacker can't leverage this functionality externally, but this still really isn't great. The whole reason that we have HSTS is to prevent the user from clicking through warnings they don't really understand. This bypass mechanisms took it from the user having to do 2 clicks on 'Advanced' and 'Proceed' to being 7 keystrokes instead. To me that's hardly enough of an improvement to be worth it and a shame that such a fundamental security mechanism as HSTS can be so easily bypassed, totally defeating the protection it offers.


It's been like this for a while

It may surprise you to learn that this bypass has been around for a long time and when I first heard of it you didn't bypass the warning by typing in badidea, you had to type in danger instead. As should be expected with these kinds of things the knowledge, even though not intended for the masses, eventually becomes more and more available. In Dec 2015 the bypass word was changed from danger to badidea because it was being used more and more widely and could be found online in forums and discussions as a helpful suggestion to get rid of those pesky warnings. You can see the Chromium bug where the bypass word was changed right here. Funnily enough a bug was raised shortly after that to say the bypass word no longer worked.

You can see the current badidea string defined in the Chromium source here, a diff of the commit where it was changed to badidea on 10th Nov 2015 here and the diff when the danger bypass was first added on 22nd Aug 2014 here.


Should this bypass exist?

For me, this is a pretty simple 'no', it should not. This bypass fundamentally breaks the protection offered by HSTS and HPKP and does so in a really trivial to execute manner. The reason that I've chosen to write about this now is that I saw a couple of tweets from quite prominent Twitter accounts recently that talked about this, which subsequently got a lot of re-tweets and engagement, meaning the cat's out of the bag (more so than it already was). Those tweets also prompted a couple of questions to me on the subject of HSTS and HTTPS so I figured I'd just address them with a blog post instead. So far the only arguments I've heard coming in for this bypass are pretty weak and the underlying problem can be fixed in much better ways. That's not to say I've heard all arguments for having it, and I'm sure there are more, so please drop by in the comments below if you have other ideas.


Losing it would make things harder for developers

There are countless organisations around the world with countless teams of developers in them and we've recently seen a drive towards HTTPS across the entire web. These developers may use local test servers/services, split-horizon DNS and all kinds of other weird, wacky and wonderful setups. If their company domain has HSTS, and includeSubDomains is set to cascade it down, then it could have a negative effect on dev and test environments across the board. This bypass allows them to continue using those services with the fatal certificate warning being bypassed.


Power users should be able to override the browser

Another one with quite a vehement declaration is that power users should be able to override the browser. The browser is telling them that the connection is not secure, for whatever given reason, but they should be able to override that warning having made an informed decision. The bypass should remain as the mechanism by which they can override the warning.


Personally, I don't think that either of those two arguments stand up to much scrutiny and there are far better ways to achieve a solution for both of them. Honestly, I think there's a way to solve any problem you would come across without needing the bypass at all.


Solutions

The problem only arises when you're using a technology like HSTS or HPKP that makes certificate warnings a fatal error. It also then only occurs when you're using those technologies on domains that are shared with developers/testers/ or power users that might encounter these warnings. In no particular order there are a few things that you could do to work around this.


Use a dedicated test domain

If you're going to spin up test or dev infrastructure don't do it on a subdomain of your corporate domain. If you're main website is acme-corp.com, don't use test.acme-corp.com, even with split-horizon DNS, as your testing environment because things like HSTS and HPKP will cascade down. Way back in 1999 this problem was already solved with the reservation of 4 TLDs for testing purposes: .test, .example, .invalid and .localhost. Put your environments on acme-corp.test or, if you really want a publicly addressable domain, buy something like acme-corp-test.com to segregate it from domain wide policies.


Install a private root CA

This one can be a little trickier but you can always setup your own internal CA to issue valid certificates for subdomains you're having problems with. If you want to know more about this you can check out The Best TLS Training in the World which guides you through the process of building your own private CA or use one of the many resources online.


Use the Chrome flags

Chromium has features built in like the --ignore-certificate-errors flag that does, well, exactly what it says but I'd recommend the more specific --ignore-certificate-errors-spki-list. This allows you to specify a list of what are essentially HPKP values that will cause Chrome to bypass certificate validation if they are found. More details here.


Outside of these scenarios I really can't think of a situation where you have a genuine need to bypass these warnings but aren't in a position to do so in a safe and proper way. This is kind of the whole point of having these mechanisms is that only those who should be able to bypass them can actually bypass them, but not the user sat at the keyboard. Once this information spreads further and further and people know that all you have to do is type badidea to get around the annoying warnings, we're just going to see more and more harm caused. Those of us that need to get around them can with the proper tools and methods, I think it's time to drop the badidea.

Author image
About Scott Helme
United Kingdom Website
Security researcher, entrepreneur and international speaker who specialises in web technologies.