Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
HEIST: HTTP Encrypted Information Can Be Stolen Through TCP-Windows [pdf] (tom.vg)
129 points by jerf on Aug 5, 2016 | hide | past | favorite | 59 comments


The techniques are interesting and clever, but isn't this "attack" only possible on websites that fail to properly protect against unapproved cross-origin requests, meaning they would be vulnerable anyway?

I re-read the specs to make sure [1] but isn't it on the server to alter the response to potentially nothing if the cross-origin response didn't come from source the server expects?

The paper says:

"Similar to the defense of blocking 3rd-party cookies, the web server could also block requests that are not legitimate. A popular way of doing this, is by analysing the Origin and/or Referer request headers. However, it is still possible to make requests without these two headers, preventing the web server to determine where to request originated from. As a result, this technique can not be used to prevent attacks"

On the contrary; the cross-origin access control spec (last edit in 2014) has an entire section on how to prevent malicious cross-origin requests like this, with verbiage like:

"This extension enables server-side applications to enforce limitations (e.g. returning nothing) on the cross-origin requests that they are willing to service."

If the server properly implements cross-origin access control by, say, returning nothing, the malicious cross-origin requesting script can't perform reflection attacks, and there's nothing interesting to measure with TCP windows and compression and the like.

[1] https://www.w3.org/TR/access-control/


The thing is: this attack doesn't even use CORS. It just sends a GET request to an URL and looks at the timing, which can be done using the fetch/Resource Timing APIs.

Here's a JSFiddle to play around with this[1], based on the code in the paper, using GitHub's account page as an example. You'll notice that the request succeeds and the fiddle has access to timing information. Inspecting the requests will show that there are no CORS headers being sent (like Origin) based on which the target could prevent the request from being served. (There's the Referer header, I suppose, but blocking the request based on that would break pretty much any third-party link to that page.)

I've tested this against various high-profile sites that include sensitive information (Google's account page, Twitter's account page, etc.), and it worked just fine on each of them. Most of them also have a parameter reflection vector (typically the full request URL is included somewhere on the page, which should be enough), so I'm pretty sure each of those sites are potentially vulnerable (though I'm not sure if calling a site vulnerable is the right approach here).

[1]: https://jsfiddle.net/39rsn2kg/


Would inclusion of a small random timeout before serving the request solve this? Would not the load balancer activity cancel the effect?

If anything, adding random garbage to the error page to approximately match the size of a normal response should make the attack useless.


Typical (WAN) network conditions are not all that different from a small random timeout, and these kind of attacks still work. Adding random noise just means you'll need more samples, but statistics are going to win eventually. I guess a combination of random noise and tight request rate limiting might mitigate this in practice (in exchange for a DoS vector, I suppose).


What will break if the fetch/timing APIs are turned off in the browser?


The Resource Timing APIs are typically used for performance monitoring. I expect well-behaved sites would degrade gracefully if those APIs aren't available (because they're not universally available anyway - Safari, for example, doesn't seem to have implemented them at all).


> fail to properly protect against unapproved cross-origin requests

It is not standard to block cross origin requests, in fact it rare or impossible in many cases.

It is standard to block cross origin requests that perform an action, usually a POST request.

But a GET request that just gets data is normally perfectly allowed cross origin. If I click a link from Google search results to the reddit homepage, that's a cross origin GET request, but reddit has to allow it, and recognize me as logged in. Also anything that could be embedded (such as an embedded Facebook comment box) would be required to allow cross origin GET requests.


Your point is fair; you're entirely correct, but allow me to clarify mine. The existing CSP configuration on the 'unsuspecting' server will do one of two things:

[a] allow the cross-origin request to be made, in which case the malicious website could've just made the actual request instead and obtain the body of the actual response without any of this BEAST/CRIME trickery

[b] deny the cross-origin request, in which case there is no reflected data in the response, preventing the malicious website from performing the reflected data or data-comparison attack demonstrated in the paper

(If I'm wrong, what am I missing?)


As far as I know, if you do a regular GET or POST using XHR or the Fetch API, the server still replies with the full content, even with CORS blocking it - it's just that the browser doesn't let the fetching code read the actual content. That is, the CORS restriction is applied in the browser after the response has been sent, not in the server.

There is a preflight mechanism which the browser can use to avoid making the request at all, but that's only used for certain types of requests.


This. And even if the browser does block the request, the js probably sees that as an error code 0 (standard for cors) at which point it can use the performance timing apis.

Side channels are tough.


CSP isn't relevant. I suspect you want to talk about cors or origin headers or similar things, in which case you are missing that there's no need for a csrf vulnerability here - any GET with reflected data could do.


With this attack however doesn't the vulnerability depend on the attackers ability to see the size of the response to the Cross-Origin request?

So if the attackers JavaScript can't see a unique response it can't get the difference in size and can't execute the attack...


The attack determines the size based on the timing information returned by the Resource Timing APIs and the compression side-channel. This is described in section 2.2 of the paper.


They could use javascript to request the reddit homepage, and use TCP window stuff to see what the size was.


Unless you have open redirection on one of your routes you are right. CSP is the answer.

https://chloe.re/2016/07/25/bypassing-paths-with-open-redire...


Ah, third-party cookies, the bad idea to begin with, is causing problems again.

Hopefully this will force browser vendors to disable that misfeature by default.


Another option, for those sites which rely on third-party cookies to work (they're rare, but they do exist; so far, I've only found one), would be to scope the third-party cookies. That is, if both foo.com and bar.com do a request to thirdparty.com, each would have their own set of cookies for thirdparty.com, and both would be different from the cookies used when thirdparty.com is accessed directly.


Does the Firefox option "Accept third-party cookies: Never" mean that origin server is disallowed from setting 3rd-party cookies OR that website-initiated fetches to 3rd-party origins don't include cookies ..or both?


This setting disables both reading and writing third-party cookies. I just found a cookie testing webpage:

https://www.grc.com/cookies/forensics.htm


You mean those vendors that make money using third party cookies to track users?


Sure. Those who haven't modernized their money-making technologies yet should stop relying on this security hole. There are alternatives.


If this would be so simple you would not see flash anywhere in the web for years already. Unfortunately it's not the case.


I haven't seen flash on the web in years, because I've uninstalled it. Good riddance to bad rubbish.


why not call them by name: google


Surprisingly, we found that not only do our attacks remain possible, we can even increase the damaging effects of our attacks by abusing new features of HTTP/2.

Interesting!


The paper goes on to describe why. The short version is a big part of HTTP/2's performance comes from header compression via the HPACK algorithm. Anything that compresses can be compromised if the attacker can inject data into the compressed output. This paper does a really nice job of concisely explaining BREACH and CRIME.


There's a provision in RFC 7541 that applies here. There's a way to indicate that a header field must not be compressed. Security-critical header fields such as keys and nonces should not be compressed. The RFC notes: "Note that these criteria for deciding to use a never-indexed literal representation will evolve over time as new attacks are discovered."

So the protocol has a feature for this. Everything that sends HTTP2 needs to update the list of fields not to compress, but that can be done by the sending end without any change to the receiving end.

[1] https://tools.ietf.org/html/rfc7541#section-7.1.3


"Note that these criteria for deciding to use a never-indexed literal representation will evolve over time as new attacks are discovered."

Or, in other words: "We know that this is insecure. Maybe someone will fix it later."


True, but the HTTP/2 people were building a wrapper for data, not a security protocol. At least they put in a feature to suppress compression. Because of that, this can be fixed from one end; it's not necessary to deploy new browsers.


That casual dismissal can be applied just as casually to the entire history of networking technologies, and it would be just as lazy and intellectually dishonest.


I don't think it's that surprising, it's pretty much a truism that more features mean more complexity, chance for bugs, and attack area --- especially features which have yet to mature for a while in practical use.


Just the text, for those of you unwilling to open PDFs from security researchers:

http://pastebin.com/rG3RD6hw


A pdf probably isn't going to be able to run JavaScript in your browser (the primary mechanism that this attack utilizes. Pastebin on the other hand... ;)


No, but depending on what program you open it with it may be able to do far worse than execute javascript in a browser sandbox. [0][1]

[0]: https://blog.didierstevens.com/2010/03/29/escape-from-pdf/

[1]: https://thestack.com/security/2016/06/09/pdf-exploit-found-i...


Except some major browsers like Chrome do their entire PDF rendering in JavaScript.


Chrome's PDF renderer is a PPAPI plugin written in C++.

Firefox is the one with the Javascript-based PDF renderer.


Oops yes you are correct.

My original point still applies though.


> Firefox is the one with the Javascript-based PDF renderer.

And it shows, hence why I always disable it.


In case the ;) did not make it obvious, this comment was meant to be taken as sarcasm.


This sounds very similar to the Time attack from 2013. https://youtu.be/rTIpFfTp3-w . I hope they got credited.

They used a timing side channel attack to extract data from a response when compression was enabled and user data is reflected back in a response. This attack can be done inside the browser and abuses how data is segmented when sent over tcp.



See also, another cross-site timing attack from 2007 (pdf): http://crypto.stanford.edu/~dabo/pubs/papers/webtiming.pdf


Very nice.


A common way to mitigate side-channel attacks is to add random noise to the side channel. In this case the original side channel is timing of network requests. Thus we can randomize time of network packets arrival, simulating unstable network link and trading speed for security. This can be done in the browser, at OS level client-side or at the server side. It's strange this method isn't mentioned in the paper.

Also I wonder if inherently varying latency of mobile and inhabited Wi-Fi networks can by itself prevent this type of attacks.

Edit: grammar.


Actually, timing attacks almost always rely on statistical methods in practice due to the inherent noise in relying on coarse timing data. So adding random noise very rarely helps at all other than increasing the amount of data required for the already-prepared statistical methods used in the attack.


Adding noise is not going to help much. You can just run the test many times and you can use statistics. The only thing helping is deterministic noise: For every security-related thing, you have a deterministic delay. That way you can not apply statistics. Unfortunately that won't work here, at least I don't know how it could.


purely by running (malicious) JavaScript inside the victim's browser

I've said it many times and I'll say it again: keep JS off by default and enable it only for the few trusted sites that absolutely need it. Interestingly, the authors mention disabling 3rd-party cookies as a countermeasure, but not JS.


Agreed. Surf makes that easy, CTRL-SHIFT-S to enable JS for the current page. It's downright annoying when I use another browser now. Ditching JS makes everything faster.

http://git.suckless.org/surf/log/?h=surf-webkit2

I have modded it a bit: https://github.com/jakeogh/glide (not well tested)


Is there a chrome plugin for that? activate JS with a key binding and automatically refresh the page.


Not sure. There's a FF plugin: https://addons.mozilla.org/en-US/firefox/addon/yesscript/?sr... and if you disable JS by default it's a quick way to enable it per domain.


Yeah, tried that a bunch of time only to find it sooo annoying that I go back to JS. It's just not worth it clicking on "enable JS" for every new page you open.


It's not that simple, browser vendors don't really want you to do that. Google even outright sabotaged such behavior in chrome some time ago. You had to type in url masks manually to enable javascript for trusted sites.


Huh? Per-site Javascript is controlled through the site permissions UI like everything else in Chrome-- that's the popover that comes up when you click the page or lock icon in the address bar.

There's even an icon that appears on the right side of the address bar when Javascript is blocked, giving the option to add an exception if clicked.


You probably don't use chrome with disabled javascript, so you haven't noticed the change. It was broken on purpose for a couple of months.


that will break the Internet.


The internet is not javascript, no matter how hard everyone tries to pretend it is.


I argue JS broke the internet. Executing a provided program to read content mixes the layers in a anti-user way.


I'd argue JS drove the internet to its present state.


almost perfectly acrostic




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

Search: