Bypassing CSP script nonces via the browser cache
CSP script nonces can be used to mitigate XSS attacks. Each legitimate script on a page should be outfitted with a random nonce that gets regenerated at every pageload. Before the page has loaded, the attacker has no way of guessing the nonce, and thus the attacker cannot outfit the injected scripts with the correct nonce. In order to mitigate the attack, the browser will only execute scripts that carry the correct nonce.
Script nonces, however, are incompatible with caching mechanisms. Browser caches, server-side caches, Service Workers or the HTML5 AppCache can break the protective capabilities. This page demonstrates one examplary scenario in which script nonces can be circumvented when caching is active.
This attack works if a cacheable page has an XSS vulnerability where location.hash or other non-URL sources (e.g. window.name, document.referer, post messages, etc.) are echoed somewhere in front of a legitimate, nonced script.
- Open this page in an incognito window.
- The iframed, cross-domain page at http://104.199.27.121/csp/nonces.php uses CSP + script nonces to mitigate XSS: Content-Security-Policy: script-src 'nonce-{{random}}'; default-src 'none'
- Via the XSS vulnerability, the attacker first injects a form with an opened textarea at the end.
- When the user clicks the "submit" button (e.g via Clickjaking), the browser submits the form to the attacker's server including the rest of the HTML code of the page that is contained within the open-ended textarea
- The server extracts the nonce from the code.
- This page polls the server for the nonce and once received uses it to execute the attack by loading the vulnerable page from the browser cache.
- As the page is loaded from cache, it will reuse the previous nonce and thus the attacker can use the obtained nonce to launch the attack.
- In order to demonstrate that CSP is indeed enabled, this page injects two scripts: One with the nonce and the other one without the nonce. If you see two alerts, CSP is not active. If you see only one alert, CSP blocked the second script.
Click the button to launch the attack.