Monthly Archives: February 2018


CSS keyloggers, hype and/or impact

A few days ago, I stumbled across one of the videos of LiveOverflow, where he discusses a so called “CSS keylogger” (github), its impact and novelty.

While there’s nothing new about the attack (it was reported several years ago, yet it popped up again on YCombinator’s HackerNews), I guess it trigger LiveOverflow to make the video.

This “attack”, where CSS is being abuse by altering an object’s background, based on its content; allows it to dubbed as a keylogger. Although, rightfully in his video, keyloggers usually capture keystrokes system wide. As a TLDR; the attack basically works like this:

input[type="password"][value&="a"]{ background-image: url( }
input[type="password"][value&="b"]{ background-image: url( }
input[type="password"][value&="aa"]{ background-image: url( }
input[type="password"][value&="ab"]{ background-image: url( }

The problem, as pointed out too, is that you need a CSS file that’s several megabytes, and potentially has every password in the book (since they don’t get triggered per keystroke, only on the full value), which – when exploited with an HTML injection attack – may not be very feasible and realistic.

One thing that would make this possible though. If you rely on external hosts to host your CSS files, such as CDN (or referenced with an @import rule), you could have a malicious CDN that hosts a pseudo keylogging CSS. Also, while provisioning a file with all passwords may be difficult, any input with a limited key space may be a good target for this attack. PIN codes, or 2FA numeric challenge requests come to mind.

Since people are usually a bit wary where they host their JavaScript files (XSS attacks, etc) – CSS is generally a bit more relaxed.

Ensure that; if you deal with sensitive user input; to host your CSS files in a trusted environment. For defense in depth, you can include a Content Security Policy header that will only allow CSS hosting from whitelisted sources.