During the last few weeks I’ve been looking at the security of some popular security extensions and one of the extensions that I checked out (which I also use myself) was HTTPS Everywhere. After some hours of analysis I managed to disable it by just viewing a HTML page. In fact, I managed to disable any extension and most (including HTTPS Everywhere) without any user interaction!
Finding the bug
I started by examining the source code to HTTPS Everywhere, hoping to find some easy miss in the “Block all HTTP requests” implementation, but to no avail.
After a while, I discovered (to my surprise) that by just accessing the extension using the “chrome-extension” URI handler, extension was disabled. In fact, this didn’t only work on the HTTPS Everywhere extension, but all Chrome extensions I tested!
Next step was to figure out how to make a user access “chrome-extension://gcbommkclmclpchllfjekcdonpmejbdp/” (“chrome-extension” URI for HTTPS Everywhere). Tricking a user into pasting the “chrome-extension” URI in their address bar was just too much user interaction for for a feasible attack.
Triggering the bug automatically
The first thing I tried was to load the “chrome-extension” URI using an <img> tag, but I was left with this message:
Damn. We’re not allowed to load it and there’s really no reason for any extension to add the empty “chrome-extension” URI to the web_accessible_resources list. But maybe there’s a way to send a request there anyway? Luckily, Cure53 has tried to enumerate all the ways to make a browser issue a request in the HTTPLeaks project. I used it to try to load the “chrome-extension” URI in all the different ways.
Most of the requests were blocked, as expected. But there was one test case that wasn’t blocked! Requests issued via the <a ping> attribute. The ‘ping’ attribute, if present, sends the URLs of the resources a notification/ping if the user follows the hyperlink.
This is the PoC (proof of concept) combining the discoveries that would disable HTTPS Everywhere by just rendering the HTML:
<a ping="chrome-extension://gcbommkclmclpchllfjekcdonpmejbdp/" id="link"></a><script>link.click()</script>
Aftermath of rendering that HTML:
It turned out that the extension corruption issue was reported in a separate report and by the time I reported the combination of the two issues, the fix for the corruption issue was already out in Chrome Beta! Both issues are now fixed in the latest stable version.
Just to be clear, the people developing HTTPS Everywhere were not at fault when it comes to these bugs. However, the bugs could be used to disable the extension.