During the last three years, the security research community has been having a lot of fun with SSL/TLS uncovering a few nifty attacks. First, in 2011, Juliano Rizzo and Thai Duong released the details about the BEAST attack on Transport Layer Security (TLS) at the ekoparty Security Conference in Buenos Aires, Argentina. I wrote a brief overview of the attack at the following blog post:
http://blogs.cisco.com/security/beat-the-beast-with-tls
In 2012, again at the ekoparty Security Conference in Buenos Aires, Rizzo and Duong revealed a compression side-channel attack against HTTPS called CRIME. This year at Black Hat USA, Angelo Prado, Neal Harris, and Yoel Gluck uncovered a new attack and a tool they called BREACH, which is based on some of the previous research by the folks behind CRIME.
The following is a timeline of all this research and tools:
What is the difference between CRIME and BREACH? They look pretty similar.
Both attacks leverage HTTP compression. Compression side-channel attacks are not new. Research in this topic started about a decade ago. On the other hand, CRIME did bring this research into reality. An attacker could launch CRIME to recover the headers of an HTTP request. HTTP headers typically include cookies during user authentication exchanges in web applications. BREACH leverages compression and takes advantage of HTTP responses. HTTP responses are compressed using the typical HTTP compression mechanisms, such as gzip and deflate, and do not rely on TLS-level compression, which is what CRIME leverages. Additionally, all versions of SSL/TLS are affected and this attack works with any cipher suite.
In order for an application to be vulnerable, it must use HTTP-level compression, reflect user-input in HTTP responses, and expose CSRF tokens in HTTP response bodies.
What is HTTP compression?
The most commonly used compression schemas are gzip and deflate. However, vendors like Google have created other methods such as the Google Shared Dictionary Compression Over HTTP (SDCH) schema. The gzip specification is defined in RFC 1952 and deflate is defined in RFC 1951.
You can use many different tools and commands to show if your web app accepts compression. In the following example, I used curl to show the header response of a test server (omar.cisco.com).
omar@omar:~$ curl -sv -H 'Accept-Encoding: gzip,deflate' http://omar.cisco.com * About to connect() to omar.cisco.com port 80 (#0) * Trying 127.0.1.1... connected > GET / HTTP/1.1 > User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3 > Host: omar.cisco.com > Accept: */* > Accept-Encoding: gzip,deflate > < HTTP/1.1 200 OK < Date: Fri, 02 Aug 2013 23:50:42 GMT < Server: Apache/2.2.22 (Ubuntu) < Vary: Cookie,User-Agent,Accept-Language,Accept-Encoding < Content-Encoding: gzip < Content-Length: 11207 < Content-Type: text/html; charset=utf-8 < { [data not shown]
Other tools such as the HTTP Compression Checker at can be used.
Can I mitigate this attack? Should I disable HTTP compression everywhere?
There are several ways to mitigate this attack. Disabling HTTP compression is the obvious mitigation; however, this will affect the performance of your web applications. Another option is separating secrets from user input by using input-less servlets and chunked secret separation.
Cross-Site Request Forgery (CSRF) protection everywhere is probably unrealistic, but following best practice techniques such as those explained by OWASP do help mitigate this attack:
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
An alternative is to “perform randomization” and masking by XORing with a random secret per request; however, this could also be tricky and requires an application change.
The attack requires hundreds or thousands of requests from the same client IP to the same server/application. You could also rate limit these requests. However, it is not uncommon for certain applications/implementations (for example, JSON) where clients could generate numerous requests.
In addition, the Cisco Intrusion Prevention System (IPS) Signature 2580/0 can be used to detect this attack.
Additional References
The following are additional references about this attack:
IntelliShield Alert
This attack has been documented in the following IntelliShield Alert 30249 and has been assigned Common Vulnerabilities and Exposures (CVE) ID CVE-2013-3587
CERT/CC Vulnerability Note
http://www.kb.cert.org/vuls/id/987798
Research Paper
http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf
Black Hat USA Presentation
http://breachattack.com/resources/BREACH%20-%20BH%202013%20-%20PRESENTATION.pdf
On the client side, you can defend yourself with Firefox addons such as CsFire or RequestPolicy, which give you control over cross-site requests. CsFire anonymizes by default, RequestPolicy blocks by default. Either one should prevent both CRIME and BREACH.
Hi Thrawn,
Thank you for the pointer! Good suggestions. FYI: CsFire is also available for Chrome.
Thanks again!
Omar
Related to performing randomization:
Would it be helpful to set a random-length ‘noise’ cookie on every request? That could be done at the proxy level, rather than the application level.
It might still be possible to extract secrets by making many requests for each string and performing statistical analysis, but it would change the attack from 30 seconds to several hours, in which time the victim may well have left the attacker’s website.
Great suggestion. This could definitely be mitigated at the “proxy-level” using randomization, as you suggested. The main caveat is that this mitigation will also require significant amount of data to be sent and randomize; subsequently, making it very challenging to implement.
Hmm…I don’t think I was clear. I didn’t mean to suggest that the ‘noise’ cookie should actually be used for anything. It just needs to exist, with a random length each time. That ought to be enough to mask the subtle length changes that the attacker is looking for.
With enough guesses, you could analyse the average length change for each inserted string, and still extract the secret(s). But it would blow out the attack time from 30 seconds to hours, and in the real world, that means it will often fail. The victim will finish watching the decoy lolcats video and close the website long before the attack completes.
As far as I can tell, that would be pretty simple to implement, and the amount of extra traffic caused by the cookies would be far less than the savings you’d get from being able to retain compression. You’d want a decent PRNG seed, of course.
OK, so I spoke to one of the researchers behind BREACH, and he indicated that he thinks the attacker is able to distinguish between headers and response body. So cookies wouldn’t help. C’est la vie. I guess inserting random text into the response body would be the closest.