Tuesday, September 11, 2012

If it's a CRIME, then I'm guilty

tldr: see bottom for the script that demonstrates what CRIME might do.

A secret crime 

Juliano Rizzo and Thai Duong did it again. Their new attack on SSL called CRIME, just like their previous one, BEAST is able to extract cookie values (to perform a session hijack) from SSL/TLS encrypted sessions. BEAST was a chosen plaintext attack and generally required:
  • Man-in-the-middle (attacker monitors all encrypted traffic)
  • Encrypted connection to attacked domain (e.g. victim uses https://mybank.com ) with cookies
  • Adaptive Javascript code able to send POST requests to attacked domain
Javascript code tried bruteforcing the cookie value character-by-character. The m-i-t-m component was observing the ciphertext, looking for differences, and once it found one, it communicated with the Javascript to proceed to next character.

CRIME should be similar:
By running JavaScript code in the browser of the victim and sniffing HTTPS traffic, we can decrypt session cookies," Rizzo told Threatpost. "We don't need to use any browser plugin and we use JavaScript to make the attack faster, but in theory we could do it with static HTML. (source)
but the details are not yet known, they are to be released later this month at Ekoparty.

However, there are already speculations on what could the attack rely on. In fact, Thomas Pornin at security.stackexchange.com have most likely figured it out correctly. The hypothesis is that Rizzo and Duong abuse data compression within the encrypted connection. It's likely as e.g. Chromium disabled TLS compression recently.

Compression-based leakage

Thanks to Cross Origin Resource Sharing it is possible (and easy) for JS to send POST request with arbitrary body cross domain. One has limited control over request headers though - e.g. the cookie header will be either attached in full or not at all (it's not possible to set cookies cross-domain). But, the attacker can construct request that looks like this:
POST / HTTP/1.1
Host: thebankserver.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1
Accept: */*
Cookie: secret=XS8b1MWZ0QEKJtM1t+QCofRpCsT2u
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

POST / HTTP/1.1
Host: thebankserver.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1
Accept: */*
Cookie: secret=?

To put it simply, in the POST body we're duplicating part of POST headers. This should compress very nicely. We would know most of the header values (from browser fingerprinting, navigator object etc.), only the cookie value is unknown.

But, we can bruteforce the first character of the cookie by including it in the POST body (we have no control over headers) after the secret= string. By observing the compressed ciphertext length (man in the middle) for all such requests we should be able to spot the difference in one of them. The ciphertext would be shorter due to better compression (longer string occured twice in the request). Then, communicate with JS to proceed to next character and the process continues until the whole cookie value is bruteforced.

That's the theory, at least.

PoC or didn't happen !

There's no time to repeat the whole man-in-the-middle, adaptive JS, encrypted connection set up, so xorninja wrote a script to check the length of zlib deflated HTTP request strings and deduce the cookie values from there. It didn't work, so I've modified the code by adding an adaptive algorithm (encryption length does not always change, sometimes you have to also mutate the POST body to be certain of a character value etc.)

And it works.
Proof of concept can bruteforce the cookie value based on zlib deflated string length only. Cookies can be of arbitrary lengths.

So, what next?

This PoC would have to be included in the whole SSL/mitm/Javascript BEAST-like context so we can check if it actually works in browsers and leaks real-life cookies. Feel free to experiment. I'm waiting for the actual CRIME disclosure.

Friday, August 24, 2012

Hack In Paris talk and future events

Videos of recent Hack In Paris 2012 conference have just been published, among those there is a recording of my talk: "HTML5 - something wicked this way comes":



With accompanying slides:



Plans for next few months:
  • BruCON (24-25.09, Ghent, Belgium) - Kyle 'Kos' Osborn & Krzysztof Kotowicz - Advanced Chrome Extension Exploitation
  • Security BSides (12-14.10, Warsaw, Poland) - I’m in your browser, pwning your stuff: Atakowanie poprzez rozszerzenia Google Chrome
  • Secure 2012 (22-24.10, Warsaw, Poland) - Atakowanie przy użyciu HTML5 w praktyce
And a few neat exploits in the queue, waiting to be released ;)

Friday, August 17, 2012

How Facebook lacked X-Frame-Options and what I did with it

In September 2011 I've discovered a vulnerability that allows attacker to partially take control over victim's Facebook account. Vulnerability allowed, among other things, to send status updates on behalf of user and send friend requests to attackers' controlled Facebook account. The vulnerability has been responsibly disclosed as part of Facebook Security Bug Bounty program and is now fixed.

Thursday, July 26, 2012

XSS ChEF - Chrome extension exploitation framework

Recently I've been busy with my new little project. What started out as a proof of concept suddenly became good enough to demonstrate it with Kyle Osborn at BlackHat, so I decided I might just present it here too ;)

Thursday, July 19, 2012

CodeIgniter <= 2.1.1 xss_clean() Cross Site Scripting filter bypass

This is a security advisory for popular PHP framework - CodeIgniter. I've found several bypasses in xss sanitization functions in the framework. These were responsibly disclosed to the vendor and are now fixed in version 2.1.2. (CVE-2012-1915).

Friday, April 6, 2012

Fun with data: URLs

Data URLs, especially in their base64 encoding can often be used for anti XSS filter bypasses. This gets even more important in Firefox and Opera, where newly opened documents retain access to opening page. So attacker can trigger XSS with only this semi-innocent-link:
<a target=_blank href="data:text/html,<script>alert(opener.document.body.innerHTML)</script>">clickme in Opera/FF</a>
or even use the base64 encoding of the URL:
data:text/html;base64,PHNjcmlwdD5hbGVydChvcGVuZXIuZG9jdW1lbnQuYm9keS5pbm5lckhUTUwrMTApPC9zY3JpcHQ+
Chrome will block the access to originating page, so that attacker has limited options:

But what if particular XSS filter knows about data: URIs and tries to reject them? We bypass, of course :) I've been fuzzing data: URIs syntax recently and I just thought you might find below examples interesting:
data:text/html;base64wakemeupbeforeyougogo,[content] // FF, Safari
data:text/html:;base64,[content]
data:text/html:[plenty-of-whitespace];base64,[content]
data:text/html;base64,,[content] // Opera


Here are full fuzz results for vector:
data:text,html;<before>base64<after>,[base64content]

BrowserBefore (ASCII)After (ASCII)
Firefox 11 9,10,13,59 anything
Safari 5.1 9,10,13,59 anything
Chrome 18 9,10,13,32,59 9,10,13,32,59
Opera 11.6 9,10,13,32,59 9,10,13,32,44,59

Not a ground-breaking result, but it may come in handy one day for you, like it did for me.

Tuesday, March 27, 2012

Chrome addons hacking: Bye Bye AdBlock filters!

Continuing the Chrome extension hacking (see part 1 and 2), this time I'd like to draw you attention to the oh-so-popular AdBlock extension. It has over a million users, is being actively maintained and is a piece of a great software (heck, even I use it!). However - due to how Chrome extensions work in general it is still relatively easy to bypass it and display some ads. Let me describe two distinct vulnerabilities I've discovered. They are both exploitable in the newest 2.5.22 version.

tl;dr: Chrome AdBlock 2.5.22 bypasses, demo here and here, but I'd advise you to read on.