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 script evaluation.
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:
The CSP used is this one:
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! 🤪