To some limited degree (you can detect presence, not position or number of occurences of character), you can do CSS only 'keylogging' even for non-reactive (sans JavaScript) input: you don't have to use attribute selector (which does't work without physical updates), but can exploit webfont with single letter `unicode-range` chunks. Posted it [1] to CrookedStyleSheets [2] some time ago:<p><pre><code> <!doctype html>
<title>css keylogger</title>
<style>
@font-face { font-family: x; src: url(./log?a), local(Impact); unicode-range: U+61; }
@font-face { font-family: x; src: url(./log?b), local(Impact); unicode-range: U+62; }
@font-face { font-family: x; src: url(./log?c), local(Impact); unicode-range: U+63; }
@font-face { font-family: x; src: url(./log?d), local(Impact); unicode-range: U+64; }
input { font-family: x, 'Comic sans ms'; }
</style>
<input value="a">type `bcd` and watch network log
</code></pre>
[1] <a href="https://github.com/jbtronics/CrookedStyleSheets/issues/24" rel="nofollow">https://github.com/jbtronics/CrookedStyleSheets/issues/24</a>
[2] <a href="https://news.ycombinator.com/item?id=16157773" rel="nofollow">https://news.ycombinator.com/item?id=16157773</a>
Hmm, that's pretty bad. CSS probably shouldn't be able to read password inputs.<p>Edit: This doesn't seem to work for me in Chrome 63.0.3239.132<p>Edit 2: OK, so it appears that this will only work on a password input that updates its "value" attribute with the typed in value. This doesn't happen unless there is JavaScript that updates the value attr with the input.value
This has nothing to do with vulnerabilities in CSS or Javascript. It has to do with ill-conceived authentication implementations, written in Javascript, that save passwords in the DOM using attributes that are then accessible via CSS. That is a vulnerability on the website itself. It is also an idiotic thing to do.
This is neat but doesn't really work as an attack.<p>The CSS selectors work on the value HtmlNode attribute rather than the Javascript "value" value, which aren't linked normally. The Instagram password field mentioned in the readme.md DOES work this way due to some custom javascript, for reasons that escape me.<p>[edit] Other people pointed this out first.<p>Also, if you are going to all the trouble of making an extension to inject your evil CSS into a page, why not go the whole hog and inject evil ecmascript instead?
This exploit might be defeated with the following css:<p>input[type="password"] {
background-image: none !important;
}<p>And if the exploit uses `!important` then you just need to make your selector more specific such as putting it inside an id. If you have malicious javascript running on your page there are better ways to steal data. I feel there is low risk of coming across this problem in the wild.
I've been noticing a lot of CSP talk lately, how CSP is the end-all be-all solution for lots of these types of attacks. Makes me think we should have more articles about how to properly implement a CSP!
(content security policy-prevents requests to websites not on the white-list -- the background image request would be rejected)
No it does not. CSS selectors do <i>not</i> apply to input content and `[value]` selectors apply to attributes, which are <i>not</i> updated by just typing in it.<p>This is <i>not</i> a CSS keylogger if you need to update the attributes with the input value via JS.<p>Edit: this apparently works on React sites because React seems to update the `value` attribute as well. Maybe <i>that</i> should be fixed as it’s unnecessary.
To be really dangerous, I think this would need to defeat client-side cache strategies. If the browser caches each resource, the server-side reads wouldn't account for repeated characters or overall length with perfect accuracy. Consider palindromes like "racecar."<p>This would still put many, if not most, passwords within guessable striking distance, for anyone able to intercept plain-text HTTP traffic, between Alice (the client) and Bob (the CSS image resource server).
I wonder if it's possible to make auto-updating CSS. CSS can use @import url("another.css"), and "another.css" might be returned with delay and import "another2.css", but I'm not sure if browser would process current css before it'll import everything.<p>If this would work, it could spy even without React. Detect first character, then server returns next CSS to detect second character and so on.
You'd have to have all permutations of any length password in the css file AND it would have to be pre-filled using the value attribute.<p>The original post on this talks about it in more detail:<p><a href="https://www.mike-gualtieri.com/posts/stealing-data-with-css-attack-and-defense" rel="nofollow">https://www.mike-gualtieri.com/posts/stealing-data-with-css-...</a><p>Summary: A method is detailed - dubbed CSS Exfil - which can be used to steal targeted data using Cascading Style Sheets (CSS) as an attack vector. Due to the modern web's heavy reliance on CSS, a wide variety of data is potentially at risk, including: usernames, passwords, and sensitive data such as date of birth, social security numbers, and credit card numbers. The technique can also be used to de-anonymize users on dark nets like Tor. Defense methods are discussed for both website operators as well as web users, and a pair of browser extensions are offered which guard against this class of attack.
Interestingly, you can defeat this key logger by typing the last character first, use the arrow key to go left and type in the rest. This works because the CSS selector only matches the end of the value input.
This isn’t a problem. CSS could already control what’s displayed and what effect it has. It could already make clicking “next page” open an invisible chat to their account, your password box send your password as a message, and your message from a friend read anything they want. It’s always been a trusted asset.<p>What might be a problem is developers not treating it as such.
Couldn't Content Security Policy (CSP) [1] be used to mitigate this attack?<p>[1]: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" rel="nofollow">https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP</a>
I can't seem to make it work from a web page. Perhaps it's for extensions only?<p><a href="https://jsfiddle.net/tdwsw6zo/3/" rel="nofollow">https://jsfiddle.net/tdwsw6zo/3/</a>
One way of mitigating this is to have strong passwords NOT in alphanumeric characters (if allowed by website), such as mixing emojis with Asian characters.
CSS has gone too far. At least when I'm worried about a nasty javascript attack from a site I can be somewhat reassured that noscript/umatrix will work. Am I going to have to start whitelisting CSS now too? Am I too late?
ALWAYS browse with devtools open, and pay close attention to every packet that's being sent out (especially when you're not expecting any to...)