Uncovering a Bug in Cloudflare's Minification Service

tl;dr: A bug in Cloudflare’s Auto Minify service parsed // and /* ... */ within ES6 `template literals` as comments, causing it to truncate lines or entire blocks of code, leading to unpredictable behavior or in rare cases, a code injection vulnerability.

HackerOne report: https://hackerone.com/reports/302289

Background

Cloudflare’s Auto Minify service can automatically minify a website’s resources, including this one’s. I don’t want to plug Cloudflare too much, but if you’re already using them and don’t minify your code yourself, consider ticking that box for some (almost) free performance!

The Bug

I’d been experimenting with mining Monero, and while the pool I joined had a website to check how much I’d earned so far, I didn’t feel like visiting it every time and manually converting my balance to USD. I reverse engineered their API (read: popped open the debug console and watched the network requests) and wrote up some quick javascript to automate the conversion. Here’s the general idea:

const address = 'XXXXXXXXXXXXXX';
const poolUrl = `https://example.com/api?address=${address}`;

// send some requests and show the results
// ...

This worked fine in development, whether through file://, python -m http.server, or even the development mode on Cloudflare, which disables caching and minification. But as soon as I switched it off, my code broke! After reviewing the code that Cloudflare served me, I discovered that instead of giving me the code above, it instead gave me something like this:

const address='XXXXXXXXXXXXXX';const poolUrl=`https:

Yes! It stripped out everything on that line after the //! Was the service parsing that as a comment and removing it? Well, let’s try /* ... */ style comments and find out! I put together this semi-realistic contrived example:

var domain = 'hackerone';
var url = `www.${domain}.com/*`;
console.log(url);
var other_url = `www.${domain}.com/*/`;

If our hypothesis is true, we should expect the crossed out section to disappear upon minification:

var domain = 'hackerone';
var url = `www.${domain}.com/*`;
console.log(url);
var other_url = `www.${domain}.com/*/`;

And hosted on Cloudflare, it looked like this:

var domain='hackerone';var url=`www.${domain}.com`;

We’re on to something!

Does this happen with regular strings as well?

var a = '// single quote double slash';
var b = "// double quote double slash";
var c = '/* single quote C style */';
var d = "/* double quote C style */";

Minified:

var a='// single quote double slash';var b="// double quote double slash";var c='/* single quote C style */';var d="/* double quote C style */";

That looks normal to me! We’ve isolated the bug to template literals, part of ES2015. This makes sense, since the current iteration of Auto Minify launched in 2011. Maybe there are other similar features that we can exploit.

Exploits

Outside of some really unfortunate edge cases, this bug really isn’t exploitable. Worst case, the javascript does something that it shouldn’t. In most cases, the javascript just breaks from a syntax error.

Here’s the best/most realistic scenario I could come up with, and it’s still super contrived:

var subreddit = 'cloudflare';
var url = `https://www.reddit.com/r/${subreddit}`;
`;console.log('what is up'); // this shouldn't run! `;

Minified, it becomes:

var subreddit='cloudflare';var url=`https:`;console.log('what is up');

which doesn’t break, but instead prints ‘what is up’ to console. I’m sure there’s some more creative way to exploit it, but it’s good enough for a PoC.

Update: As Johannes B. Ullrich pointed out in SANS’s ISC podcast,

Features like this have been used in the past to come up with benign code that turns malicious after it runs through a minifier, and since most code review is done before you run the code through a minifier, this can then be used to sneak in backdoors.

Workarounds

Due to the nature of the bug existing in the actual parser, there’s no way to get around this other than avoiding the use of // or /* ... */ in template strings, or turning off Auto Minify entirely. Luckily, Cloudflare fixed it, so it’s no longer an issue.

Timeline

The folks at Cloudflare were courteous and responded reasonably quickly.

HackerOne report: https://hackerone.com/reports/302289

Jan 03 Bug submitted on HackerOne
Jan 04 Acknowledged by staff
Jan 22 Triaged
Feb 15 Resolved, swag awarded
Mar 17 Publicly disclosed