3 ms·
The hackerone write up which this submission points to actually goes into explicit detail on what happens step by step, along with nice infographics. The TL;DR
by kbenson 7y ago
The hackerone write up which this submission points to actually goes into explicit detail on what happens step by step, along with nice infographics.
The TL;DR is that you can make the front-end see something like GET /my/supplied/url\nX:X at the end of your request, but the back-end see it as the beginning of the next request, (and the X:X turns the real GET/POST whatever info a custom header of X:XGET /real/request/url), and Slack returns that request with cookies for that person, but to a domain controlled by you when it comes back. The diagrams included in the post and the accompanying text do a better job of explaining it than I am, I think.
- bawolff 7y agoI'm also similarly confused. The post explains request smuggling really well, but doesn't really explain how that equals getting the victim's cookies. This is my understanding of the bug: * Attacker sends malformed request to slack servers. Request gets split in two. First part results in something sent back to attacker, next part of request is treated as a prefix to the next legit (victim's) http request made * Slack backend server responds to victim's request treating it as having part of the attacker's request prefixed. The merged request results in a 301 http redirect response, redirecting the victim to an attacker controlled domain. * Victim's browser gets the 301, and follows the redirect. When following the redirect, the cookie header is somehow sent to the attacker's site <-- Part i don't understand here I don't understand why the victim's browser would send the cookie header when following a redirect to a different domain. I don't understand how causing the victim to follow a cross-domain redirect would allow the attacker to extract the victim's cookie.
- JangoSteve 7y agoYes, this was precisely my question. I agree with you that the post does a great job of explaining the how request smuggling works, and how they used it to trick Slack's server into responding to the user's client with a 301 redirect to the hacker's server. But then, when they got to the part where the cookies are sent, they just said, "and the cookies are sent" with no further explanation. That's the part I'm stuck on. Is there some browser behavior I'm not remembering where it sends sensitive cookies across domains just because one redirected the browser to the other?
- Matt3o12_ 7y agoI think this rather applies to API clients which can handle that differently. A quick test for python's shows that all headers are redirect regardless: requests.request("GET", "http://localhost/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fget", headers={"x-foo": "bar", "Cookies": "abc=dcv;"}).json() { "args": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Cookies": "abc=dcv;", "Host": "httpbin.org", "User-Agent": "python-requests/2.22.0", "X-Amzn-Trace-Id": "Root=1-5e6bebe1-cd6e71729a818015a06aa7cb", "X-Foo": "bar" }, "origin": "91.58.8.128", "url": "http://httpbin.org/get" } I'm running a local copy of httpbin on localhost, so python's request should not send sensitive headers for redirects but it does. Golang is a bit more explicit about it's http client behavior: > • when forwarding sensitive headers like "Authorization", "WWW-Authenticate", and "Cookie" to untrusted targets. These headers will be ignored when following a redirect to a domain that is not a subdomain match or exact match of the initial domain. For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com" will forward the sensitive headers, but a redirect to "bar.com" will not. https://golang.org/pkg/net/http/#Client https://golang.org/pkg/net/http/#Client Though this might also cause problems if you are using sensitive non standard headers such as X-Token for token authentication, etc. So while you could probably mitigate this vulnerability on some clients, you are trusting the server to only redirect you to trusted URLs which is not the case here.
- bawolff 7y agoHmm that would make sense. The user-agent header does have "slack" in it so probably not a web browser, and its not far fetched that most libraries dont implement the same origin policy when it comes to headers and redirects.
- kevin_thibedeau 7y ago"Cookies" is not a sensitive header in a request. "Cookie" is.
- kbenson 7y agoI imagine one way to do it is to make the attacking request to a redirect. Since the back-end conflates the attacking request and the next request (or a portion of the next request), you can get that next request, including the headers (i.e. cookies) as the body/payload redirected to that external site. If the attacker controls that external site, they then can see the cookie data. Another way would be to make it so the next request is the content of a param which is displayed in some manner. For example, if it's the content to a message post to a slack forum. Those different than what they outline in the article, but neither seems unlikely to be found on the back-end in some manner. Redirects are often locked down, but not always, and finding something that sends a variable back to you (such as a form port target that you know will error "helpfully") doesn't seem like it would be hard to me.
- bawolff 7y agoI'm not sure I am understanding > I imagine one way to do it is to make the attacking request to a redirect. Since the back-end conflates the attacking request and the next request (or a portion of the next request), you can get that next request, including the headers (i.e. cookies) as the body/payload redirected to that external site. If the attacker controls that external site, they then can see the cookie data. Are you suggesting that if the backend server was setup as an HTTP proxy, you could get the backend server to proxy the merged request somewhere else? That's true, but it seems pretty unlikey that the backend servers would be setup that way. Although i think i might just be misunderstanding what you mean. > Another way would be to make it so the next request is the content of a param which is displayed in some manner. For example, if it's the content to a message post to a slack forum. I.e. you're suggesting basically using this as a CSRF attack to post part of the victims request (including secret cookie) somewhere public to retrieve later? I think this would work in certain situations but would be difficult to pull off. Its a bit more complicated because if the site was using csrf tokens you would need to make sure the victim request was a POST with a token,but that is easy enough - retry until it happens. The bigger issue is the request body would be kind of malformed. If the endpoint you are posting to accepts application/x-www-urlencoded (and not json), i imagine its interpreted super liberally. I guess the biggest issue is if ; is considered a form field separator (since user-agent usually has ; in it). I think some standards tried to promote that, but i dont know if webservers actually implement it. If they do,it would be very difficult for the attacker to control the name of the form field, and thus actually get the part they wanted publicly posted