This finding was a part of Hack the World 2017 event.
TL;DR: it was possible to leak Facebook access_token to the external domain, and authorize on the site on behalf of the user using this token.
The interesting part is not the vulnerability itself (we know that open redirects and referer leaks are usual ways to leak the tokens), but how the Open Redirect for the chain was found.
The Murphy’s law of Open Redirects: when you need open redirect – there is no open redirect.
I will tell the story from the beginning – when I started to look for a target for the Hack the World 2017 event. Airbnb program awarded double points for the discovered vulnerabilities and offered nice bounties, so I started to explore their assets.
I stopped on the luxuryretreats.com domain. After an hour of poking around, I noticed that redirect_uri check on the
https://auth2.luxuryretreats.com/api/ExternalWebUser/GetRedirectUri endpoint (which was used for Facebook authentication) doesn’t have strict uri check, and allowed arbitrary paths in the redirect_uri parameter:
There was no luck with common host validation bypasses techniques, such as HPP and URI manipulations – and there was a strict check for
https://luxuryretreats.com/string on the beginning of the redirect_uri parameter. I could control only the path, and sadly, there was no visible open redirect issues on the site. I tried to search for areas where I could exfiltrate token to the controlled destination via Referer header – without success.
Approaching the Open Redirect
Fix your Open Redirects when they are in low impact state before they start to be dangerous.
I will write a separate article about why in my opinion even low-impact open redirects (especially which came from server-side misconfigurations) should be fixed or hardened to prevent any unexpected behavior. It’s better to issue even 10$ bounty for such open redirects and make the life a little harder for hackers than move it to the out-of-scope section.
Anyway, I started to think about how can I leak the token. Usually, if there is no easy ways to do this, I start to look for misconfigurations and do extended content discovery (such as fuzzing URL parameter names, paths, exploring JS files, etc). Doing this, I’m looking for any unusual behavior.
And, I noticed one thing that caught my eye upon fuzzing the path – sometimes
https://www.luxuryretreats.com/[path] redirects to the
https://www.luxuryretreats.com/vacation-rentals – but only if specific path is given
During fuzzing, I noticed interesting behavior with 1-char paths:
when this char is present in the hostname, the 301 redirect will be issued, where the char is replaced by vacation-rentals string in both path and hostname! E.g.
This is not traditional open redirect, and most likely it was a flaw in the redirect rules on the server, but it was enough to leak the token to the external host! Luckily (for me), this domain was not registered and could be claimed
https://www.luxvacation-rentalsryretreats.com/vacation-rentals?external_access_token=[token]After this, the attacker sends the token to the OAuth endpoint:
https://www.luxuryretreats.com/externalAuthentication?external_access_token=[token]and successfully authorizes on behalf of the user with full control of the account. The Airbnb team fixed this issue very fast, and changed OAuth implementation.
Lessons learned1) Discovery of the short paths can be useful – I generated a list which consists of combinations of [a-zA-Z0-9] up to 3 chars inclusively in length and added it to my wordlists. It helped me a lot of times.
2) In most cases, you likely can leak data even if there are no visible open redirects/referer tricks – just dig deeper.
3) If the redirect_uri check isn’t strict, even if it looks secure – research it!