Earlier this week I saw this tweet by Sansec float by:
After finding skimmers in SVG files last week, we now discovered a #magecart skimmer in perfectly valid CSS. It is parsed and executed during checkout. Malware loaded from cloud-iq[.]net (faking @cloudIQApps) pic.twitter.com/Hy6b6lxJoL
— Sansec (@sansecio) December 9, 2020
window.getComputedStyle to extract the contents of the Custom Property (see here) and combine it with a function constructor and an IIFE, it’s possible to execute it.
Here’s a pen that loads a remote confetti script using the method described:
Let this underline the importance of a Content Security Policy to prevent
remote script loading .
Update: Blocking this “hack” with a proper CSP
It took me some time to figure out — as I’m no CSP expert — but turns out the
unsafe-inline keyword in the CSP’s source list is enough to block the execution of the JS-IN-CSS.
As a reminder, here are the four allowed keywords:
'none', as you might expect, matches nothing.
'self'matches the current origin, but not its subdomains.
I first thought
unsafe-inline would be insufficient here as the code does not call
eval, but apparently a function constructor is (correctly!) considered equally harmful, and therefore also blocked.
Here’s an updated demo that blocks the script evaluation:
See the Pen
The CSP used is this one:
<meta http-equiv="Content-Security-Policy" content="script-src https://cpwebassets.codepen.io https://cdpn.io https://cdn.jsdelivr.net 'unsafe-inline';" >
It works as follows:
https://cdpn.ioare there for the CodePen demo to work
https://cdn.jsdelivr.netis there to allow legitimate loading of scripts — such as a jQuery you might need — from that CDN.
unsafe-inlineis the one that prevents the execution of the JS-IN-CSS defined script by blocking the call to the function constructor
That calls for confetti! 🤪
Thank me with a coffee.
I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
Came to your site after the recent checking on the your recent houdini.how update. Anyways, great site I’ve been here before as I regularly browse quality sites to get ideas and learn new topics.
I learned about this a week ago or so myself (I think from a js newsletter) but after seeing your clear demo decided to give it a try as I can just copy/paste the code to a temp site and test.
Your original and linked CSP article is correct that the following will work to block this attack:
However that will also block all images. A modified version:
Would block just the script. If you try that and view in Chrome it shows:
The most restrictive CSP:
blocks this as well
Thanks for your kind words and input Conrad 🙂
The CSP post I linked to contained an exemplary CSP rule. What I’m more curious about is a CSP that would both allow external scripts (we might still need a legitmate jQuery from
https://cdn.jsdelivr.net/for example) and also block the passing of custom property data from the CSS to JS.
I’m not too sure if an
unsafe-inline— which is a bit more restrictive than
unsafe-eval— will do in that case, as there’s no call to
Will also try and take a stab at it … perhaps I can find a working combination.
PS: Fixed that formatting for you there 😉
UPDATE: Took me some time to figure out, but found a matching CSP. I’ve updated the post accordingly.
Leave a comment