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 meant that we could disable an extension by simply clicking a link which is very feasible for an attack. But could we make it work completely without user interaction? After quite some testing, I discovered that the simplest way worked; issuing the click event using javascript.

PoC

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:

Chrome patch

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.

End note

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.

Author

Mathias Karlsson

Freelancer

@avlidienbrunn