Thursday, September 6, 2012

The Story About Two OAuth2 Vulnerabilities

Facebook Connect Reply Attack
There is a blatant issue in facebook connect. It's vulnerable to replay attack.

Authorization 'code' expires as soon as access_token expires - approximately 60-80 minutes, during this period it can be used many times to obtain access_token. Every time you visit example.org/fb_callback?code=123qwe... you are authenticated for example.org.

FB Connect doesn't follow clear and concise countermeasures from Threat Model. Here they are with annotations:
   o  Limited duration of authorization codes - Section 5.1.5.3 [60-80 minutes are more than enough]
   o  The authorization server should enforce a one time usage restriction (see Section 5.1.5.4). [unlimited]
There are couple of ways to get 'code':
Logs. 
For example if you use omniauth with rails check your logs for
GET "/auth/facebook/callback?code=..."
I recommend to filter this parameter with built-in tool:
config.filter_parameters += [:password, :code]
Sniff
Callback is located on Client's website - and it is not always HTTPS. Your URL with code may be sniffed with MITM, browser plugins, browser history(if it has not redirects) etc
XSS
Here is a neat exploit to extract callback URL for proper redirect_uri.

<iframe src="https://www.facebook.com/dialog/permissions.request?app_id=159618457465836&display=page&next=http://magru.net/users/auth/facebook/callback&response_type=code" name="refcontainer" onload="alert(refcontainer.document.referrer)"></iframe>

1) Load authorize URL with proper redirect_uri as callback in iframe
2) get redirected on proper redirect_uri with code
3) another redirect, usually to root
4) fires up 'onload' event
5) since we are on the same origin we just go into iframe and extract 'document.referrer' - redirect_uri with code.
6) leak code and use it for replay attacks.

Mitigation:
One time usage of 'code', please. There is no sense to keep 'code' if Client already obtained access_token for it.

Vkontakte Referrer Leak
Vkontakte has one time usage of 'code'. No replay attack here... Wait, there is a similar one. VK OAuth2 has a huge flaw.
They do not require 'redirect_uri' to exchange code for token. It means there is no verification, was certain 'code' issued for proper redirect_uri or any other URL (on Client's domain).
You can get a code for
SITE.com/fake_callback_leaking_referrer?code=123qwe
and then just use it on
SITE.com/real_callback?code=123qwe
You will be authenticated.

There are literally dozens of ways to leak code: browser history, hot linked images leak referrer, clickjacking with clicking on external URL, sniffing, open redirectors(feature on some sites site.com?url=http://other.com) etc


Mitigation:
Every time you create code you must save for which redirect_uri it was issued. When code will be exchanged for token, ensure that given redirect_uri parameter is equal stored.

Result

Fixed on facebook, 2 grands $ bounty, fixed on vkontakte (for new apps only).