CRSF、配置JSONP劫持、CORS存在的cookie跨域问题

admin 2024年3月28日01:38:23评论2 views字数 4383阅读14分36秒阅读模式

前言

最近在挖SRC时遇到了JOSNP和CORS,但是进行JSONP劫持和CORS跨域请求的尝试却失败了,后来经过研究发现根本原因是cookie跨域的限制造成了,遂有了这篇文章。

关于cookie跨域的分析

影响cookie跨域的samesite和secure

2016年开始,Chrome 51版本对Cookie新增了一个 SameSite属性,为了防止CSRF攻击,陆续的各大厂商的浏览器也都适配了该属性,该属性限制了在不同情况下cookie的跨域。而Secure则是规定了cookie是否可以在http下传输,如果Secure为true,则仅在使用https时才会携带cookie。

  • 下图为不同SameSite设置的效果,当然也可以不设置SameSite,大多数浏览器在不设置SameSite时默认为Lax

CRSF、配置JSONP劫持、CORS存在的cookie跨域问题

指的一提的是,一般情况下如果设置SameSite为None,也要同时设置Secure,否则一些浏览器可能会拒绝仅有SameSite=None的设置。

CRSF、配置JSONP劫持、CORS存在的cookie跨域问题

在不同浏览器上的实验

上面的描述只是标准,具体的效果还要依赖于浏览器的实现,这里进行一波实验来验证一下上述和标准和各个浏览器的实现。

先使用小皮面板创建两个站点,test1.com和test2.com,test1.com注意设置为https访问。

CRSF、配置JSONP劫持、CORS存在的cookie跨域问题

在test1.com上部署一个设置cooke的前端页面test1.com/cookieSetting.html和一个后端处理脚本test1.com/getCookie.php,还有一个测试cookie是否携带的页面test1.com/json.php,如果携带cookie就会返回账户密码,否则返回error。

  • test1.com/cookieSetting.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cookie 设置与清除</title>
</head>
<body>

<h2>Cookie 设置与清除表单</h2>

<form action="./getCookie.php" method="post" id="cookieForm">

<label for="samesite">SameSite:</label>
<select id="samesite" name="samesite">
<option value="Strict">Strict</option>
<option value="Lax">Lax</option>
<option value="None">None</option>
<option value=" ">不设置</option>
</select>
</br>
<label for="httponly">HttpOnly:</label>
<input type="checkbox" id="httponly" name="httponly">

<label for="secure">Secure:</label>
<input type="checkbox" id="secure" name="secure">
</br>
<select id="setcookie" name="setcookie">
<option value="set">设置cookie</option>
<option value="">清除cookie</option>
</select>
</br>
<button type="submit">确认</button>
</form>


</body>
</html>
  • test1.com/getCookie.php

<?php
$simesite=$_POST["samesite"];
$httponly=$_POST["httponly"];
$secure=$_POST["secure"];
$set=$_POST["setcookie"];

// 检查是否存在名为 "secret" 的Cookie
if ($set==="") {
// 如果存在,则清除Cookie
setcookie('secret', '', time() - 3600); // 将过期时间设置为过去的时间
echo 'Cookie已清除';
} else {
// 如果不存在,则设置Cookie为 "secret=666666"
// 启用HTTPS时设置Secure标志
$secureFlag = true;
// 设置Cookie
setcookie('secret', '666666', [
'expires' => time() + 3600, // 0表示会话结束时过期
'path' => '/', // 可在整个域名下访问
'domain' => '', // 通过任何子域名都可以访问
'secure' => $secure, // 根据是否使用HTTPS动态设置Secure标志
'httponly' => $httponly, // 仅通过HTTP协议访问,防止JavaScript访问
'samesite' => $simesite, // 允许在跨站请求中发送Cookie
]);
echo 'Cookie已设置';
}
?>
  • test1.com/json.php

<?php

if(isset($_COOKIE['secret']) && $_COOKIE['secret'] == '666666') {
header("Content-Type: text/json");
echo "hack({"username":"admin","password":"123456"})";
} else {
echo 'error';
}

?>

在test2.com则部署一个跨域测试的html页面crossSite.html,来测试各种跨域的cookie携带情况

  • test2.com/crossSite.html

<a href="https://test1.com/json.php?a">link to test1.com/json.com</a>
</br>
<button onclick="window.open('https://test1.com/json.php?windowOpen')">window.open("https://test1.com/json.php")</button>
</br>
<button onclick="window.location.href = 'https://test1.com/json.php?windowLocation'">window.location.href = 'https://test1.com/json.php'</button>
<form action="https://test1.com/json.php" method="get">
<input name="get" type="text hidden" value="get"/>
<button type="submit">form get</button>
</form>
<form action="https://test1.com/json.php" method="post">
<input name="post" type="text hidden" value="post"/>
<button type="submit">form post</button>
</form>
<iframe src="https://test1.com/json.php?iframe"></iframe>
<script src="https://test1.com/json.php?script"></script>
<link rel="stylesheet" href="https://test1.com/json.php?stylesheet">
<script>
fetch('https://test1.com/json.php?fetch', {
method: 'GET', // 或 'POST',根据实际需求选择
credentials: 'include' // 允许携带 Cookie
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
</script>
<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://test1.com/json.php?ajax', true);
xhr.withCredentials = true; // 允许携带 Cookie

xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
console.log(data);
} else {
console.error('Error:', xhr.status);
}
}
};

xhr.send();
</script>
<link rel="prefetch" href="https://test1.com/json.php?prefetch">

经过上面的分析,在什么时候可以进行跨域其实已经很明了了

  • CSRF使用get和input进行跨域,当使用get进行跨域时,除了SameSite=strick的情况,都可以携带cookie;当使用post进行跨域时,按照标准,只有SameSite=None和Secure被设置时才能携带cookie。但是由于很多浏览器的实现不标准或者对于不设置SameSite的处理较为模糊,有时不设置SameSite或设置SameSite=None而不设置Secure时允许input跨域携带cookie,这要视浏览器的实现而定。

  • JSONP劫持依赖<script src>访问敏感信息,如果希望<script src>携带cookie,只有SameSite=None的时候才可以

  • CORS配置不当,对于CORS的设置就不多说了,在Access-Control-Allow-Credentials为true的前提下,由于CORS的跨域依赖的是ajax和fetch,要在这种情况下携带cookie进行跨域,同样也只有SameSite=None的时候才可以

来源:【freebuf】

原文始发于微信公众号(船山信安):CRSF、配置JSONP劫持、CORS存在的cookie跨域问题

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月28日01:38:23
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CRSF、配置JSONP劫持、CORS存在的cookie跨域问题https://cn-sec.com/archives/2594561.html

发表评论

匿名网友 填写信息