Chrome Extension CORS Security Vulnerability (fixed in 2019)

In 2018 I found a simple exploit that abuses the way Chrome extensions use CORS headers, preventing extensions from accessing remote resources loaded arbitrarily at runtime. I didn’t report it but eventually Google fixed it a year later. Note that I’m not a security researcher and not particularly sure why this bug exists, but simply found it by trying to get code execution through remote requests.

Background

In manifest v2, chrome extensions basically run loaded into your browser with a popup.html file (the window that appears when you click the extension icon, if it’s enabled) and an optional background.js file (a script that runs in the background of webpages you load). The vulnerability surrounds the way the browser’s local storage interacts with popup.html and background.js.

Attackers can abuse this exploit to not only execute obfuscated Javascript which the Chrome web store automatically rejects if detected in the extension when uploaded, but also arbitrarily execute remotely hosted code.

The exploit

If you try to make a web request for remotely loaded Javascript on the background page itself (the target), you’ll get a CORS violation and won’t be able to load the remotely hosted resource. However, you can make a HTTP request for the contents of the Javascript resource from popup.html, load it into local storage and then call exec() and execute it in background.js. In other words, for whatever reason popup.html however bypasses CORS and lets you do this. I believe the fact that localstorage is shared is intentional, however.

In practice this means you can not only remotely execute code, but obfuscate your code which normally the Chrome web store blocks (because it’s loaded at runtime) and execute all your background.js code completely remotely.

I found this when I was trying to see if I could get a remote-update system for my ~780 user chrome extension, and yeah it works (but oh boy can this be misused).

The solution

There is no reason background scripts should be able to call exec, or even access localstorage. Simply disabling either of these patches the exploit. Adding CORS headers to popup.html also works.

I didn’t publish this exploit, but Google fixed it in 2019 so they must have known about it. They removed the ability to make cross origin requests in content-scripts. In practice when I tested this popup.html now has CORS headers so you can’t just request arbitrary data.

Back