Breaking Out HSTS (and HPKP) on Firefox, IE/Edge and (possibly) Chrome. Our Black Hat research

Monday, December 11, 2017

We have been for a long time researching about HSTS, HPKP, certificate pinning and TLS technologies in general. As a collateral effect of this work, we have found some interesting weaknesses in the way Firefox, Chrome and IE/Edge implement both mechanisms HSTS and HPKP. With this research we applied to Black Hat Europe 2017 and went to talk in London last December 7th, in the briefings section. Here are some details about what we talked then, as a "digest" of the presentation itself which may be found here.


Aside from vulnerabilities such as HeartBleed, CRIME, etc. usual attacks over SSL take advantage of: 
  • Rogue certificates: that's when an attacker hacks into a certificate authority, plays in some way the CA role inside a network, or takes advantage of an procedural error, to issue her/him a certificate that looks just like the real certificate of an entity but it is fake. In the past few years we have plenty of these examples.
  • SSLStrip techniques: it consists basically in the interception of one initial unsecure connection and redirect from there all of the subsequent requests over HTTP and not HTTPS.
For the first problem, HPKP is one of the proposed solutions. It forces the browser to remember all the legitimate certificates served by the browser, because the server sends them over an HTTP header. For the second, HSTS is proposed. It consists of a header sent to make the browser remember that it always has to connect over TLS/SSL, so there is not any unsecure connection made after this header is sent.

We have analyzed how browsers implement these (relatively) new features and what we found (between some other minor mistakes) is:


As we explained when PinPatrol was delivered, Firefox uses a TXT file with a limit of 1024 entries to remember HSTS and HPKP domains. It seems that they though it was unlikely that an user would store more than that but, anyhow, they implemented a concept of "score" for each domain too.

Firefox source code coment about 1024 limit

The score indicates how often the user visits that domain on different days. Score 0 means that the header is expired or it is the first day he has visited the site. Score goes to 1 next day if he visits it again. It would go to 2 next different day (not necessarily to be the day after) he visits that site. In a nutshell, the more often (in different days) the user visit the site the higher the score. In case of having to remove one of this 1024 entries to make space (free up a slot), the one with the lower score is removed.

What we did is a Bettercap JavaScript to inject and a special website. Both send a lot of HSTS headers (what we call "junk entries") with different subdomains. Firefox, in less 2 minutes, fills up this 1024 table and starts removing legitimate domains with score 0.

Simple script to send headers from our site

What happens if a legitimate domain has a higher score and is less likely to be removed? To get that, we need to make this attack again in a different day, so our junk entries get a score of 1, and the legitimate ones with 0 score or 1 score, will probably go away. And so on.

Junk entries with Score = 0 have removed legitimate domains

If we do not want to wait a whole day, we may use a known technique by Jose Selvi called Delorean, speeding up the time in some Linux and Mac clients. Combined, we may likely evict HSTS and HPKP entries in Firefox for important domains in minutes.

Using Delorian to speed up the process, if you want to

Even if this does not work and we are not able to evict a domain from the table (evict a domain from that 1024 is equal to disable HSTS and HPKP for it and allows the Man in The middle attack), Firefox, because of this slot-based mechanism, will end up with just one single slot (the one that remains with score 0) to store HSTS entries, which will be constantly replaced by new domains with score 0 as well which, eventually, is like making HSTS useless.

If we get to fill up the 1024 entries with a score higher than 0, there will be just one slot left

Chrome has no concept of score. As we explained with our extension PinPatrol for Chrome, it stores HSTS and HPKP in a JSON file. If anyone sends a lot of HSTS and HPKP entries from a server or from a MiTM attack, Chrome will store all of them forever. Our approach here sends thousands of HSTS and HPKP requests due to the unlimited number of "pins" in Chrome for HPKP, where each request may be as large as a HTTP header may allow. Result: in about 10 minutes, this JSON file is 500 megabytes or more in the hardrive, and Chrome freezes. You can not even type a new domain anymore. The only choice is to try to delete all your settings (if you can) or remove this JSON. This attack can be done from any website that you can insert a javascript.

Lots and lots and lots of pins sent to Chrome


Basically, the function or API that manages HSTS in Windows is located in the WININET.DLL library, and it is called HttpIsHostHstsEnabled, which seems not to have any official documentation. We understand that knowing the system in depth would require extensive reverse engineering and forensic work, which is beyond the scope of this report. In recent versions of Internet Explorer (and even Edge), Microsoft uses a type of proprietary database called Extensible Storage Engine (ESE) to store HSTS data among many others. The base file with the bulk of information is usually hosted in WebCacheV01.dat file under the user profile, in WebCache folder.

With lack of documentation, this is all you can "know" from how IE/Edge store their HSTS information

This is complex since a deeper research is needed. HSTS does not seem to work properly in this browser. We have discovered the tables where this information is stored, but it only seems to work with popular domains. Incredibly, it seems that it does not remember HSTS for not so popular domains. And furthermore, even removing the cache (not the HSTS storage system) seems to not affect this entry list. We have reversed some of the APIs that should be involked to store this information they are neved used. As a PoC, we called 131 times our site, and after restarting browser, and even computer, not a single change was made to HSTS permanent tables.

Some requests do not seem to have any impact in Internet Explorer

If you want to have a look and play around with this concept, we created this webpage ( and feel free to use it.

Innovation and laboratory

No comments:

Post a Comment