HSTS support allows queries into global history




5 years ago
3 years ago


(Reporter: ie_lover, Unassigned)


Firefox Tracking Flags

(Not tracked)



(1 attachment)

I find a way to obtain a partial list of a user's browsing history, which only includes HSTS-enabled non-preloaded domains. It is quite similar to the CSS :visited trick.

If we ask Firefox to load http://example.com:443, it will definitely fail, because Firefox will make plain-text HTTP request to port 443 of the server. However, if example.com is a Known HSTS Host (meaning either the user has visited https://example.com before, or it is on the HSTS preload list), it will send request to https://example.com:443, and the request will succeed. We can use JavaScript to differentiate the two cases: in the first case, onerror event is triggered, while in the second case, onload event is triggered.

Therefore, a malicious website can include well-chosen cross-domain images and use this trick to brute-force a list of domains that users have visited. Note that the list could only contain HSTS-enabled but not preloaded websites.

Two possible fixes I can think of are:
1. always treat http://example.com:443 as  https://example.com:443 regardless of whether HSTS is set or not, while other ports are unaffected. 443 is reserved for HTTPS anyway.
2. always throw an error whenever the browser encounters a http link that explicitly specifies port 443.

By the way, this issue is not just for Firefox. At least Chrome is also vulnerable, and I have reported this issue to Google as well [1]. So I think it would be the best if this bug can be kept private until all browsers have been patched.

Please see the attachment for a proof of concept.

[1] https://code.google.com/p/chromium/issues/detail?id=436451
This is fundamentally a bug in the HSTS spec, so fixing this needs spec changes (to either Fetch or HSTS or some combination), in addition to code changes in browsers...
Ever confirmed: true
See also http://lists.w3.org/Archives/Public/public-webappsec/2014Sep/thread.html#msg108 for similar attacks.

And https://tools.ietf.org/html/rfc6797#section-14.9 where the RFC acknowledges this, though not quite as easy as the attack in comment 0.

https://hstspreload.appspot.com/ should mitigate the tracking aspects somewhat.

I'm happy to make changes to Fetch or communicate with websec in the IETF once we decide what we want to do.

(Tying HSTS to DNS, which would solve some of these issues as a page cannot intercept DNS, is a non-starter unfortunately.)
Actually the issue I describe here is different from RFC6797 §14.9. 14.9 basically says that if *.example.com is under my control, then I can cause UA to load [1-100].example.com, and only some of them return HSTS headers. Next time when users visit the site, it loads http://[1-100].example.com/check_user_proto, which returns the protocol used in request. If "https" is returned, this means #.example.com set the HSTS header last time. So one subdomain can set one bit of encoded information.

This issue is not about cookie-like tracking. It can be used to reliably determine if a user has visited a specific non-preloaded HSTS domain (not necessarily under my control).

For this issue, which fix do you think is the best?

Also an update on spec seems to be necessary, but I think we need to wait until Firefox and other browser vendors have fixed this issue (maybe in different ways), before publicly discussed this with IETF.
I just found RFC 3986 section 7.2 says:
   Applications should prevent dereference of a URI that specifies a TCP
   port number within the "well-known port" range (0 - 1023) unless the
   protocol being used to dereference that URI is compatible with the
   protocol expected on that well-known port.

So I think blocking HTTP requests over port 443 is a better way to fix this issue, since this is actually required by the spec.

[1] https://tools.ietf.org/html/rfc3986#section-7.2
Closed: 5 years ago
Resolution: --- → DUPLICATE
Duplicate of bug: 1090433
Group: core-security → core-security-release
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.