CRSF、JSONP劫持、CORS配置不当中的cookie跨域问题
字数 2776 2025-08-18 17:33:30
Cookie跨域安全机制与攻击防护详解
1. Cookie跨域基础概念
1.1 SameSite属性
SameSite是Cookie的一个属性,用于控制Cookie在跨站请求中的发送行为,主要目的是防止CSRF攻击。它有三个可能的值:
- Strict:最严格模式,仅当请求来自同一站点时才发送Cookie
- Lax:宽松模式,允许顶级导航(如链接点击)携带Cookie,但阻止跨站AJAX请求等
- None:关闭SameSite限制,允许跨站请求携带Cookie,但必须同时设置Secure属性
1.2 Secure属性
Secure属性规定Cookie是否可以在HTTP协议下传输:
- 当Secure=true时,仅在使用HTTPS时才会携带Cookie
- 当Secure=false或未设置时,HTTP和HTTPS均可携带Cookie
2. 浏览器实现差异
2.1 默认行为
大多数现代浏览器在不显式设置SameSite时的默认行为:
- Chrome、Edge等基于Chromium的浏览器:默认为Lax
- Firefox:实现略有不同,特别是在处理POST表单时
2.2 特殊要求
当设置SameSite=None时:
- 必须同时设置Secure=true
- 否则某些浏览器会拒绝设置这样的Cookie
3. 跨域场景测试与分析
3.1 测试环境搭建
-
创建两个测试站点:
- test1.com(HTTPS):包含Cookie设置、后端处理和敏感信息接口
- test2.com:包含各种跨域测试方法的前端页面
-
关键测试页面:
- test1.com/cookieSetting.html:设置不同属性的Cookie
- test1.com/getCookie.php:处理Cookie设置/清除
- test1.com/json.php:检查Cookie携带情况并返回敏感信息
- test2.com/crossSite.html:包含多种跨域请求方法
3.2 跨域请求方法及Cookie携带情况
| 请求方法 | SameSite=Strict | SameSite=Lax | SameSite=None+Secure | 未设置SameSite |
|---|---|---|---|---|
| 普通链接点击 | × | ✓ | ✓ | ✓ |
| window.open() | × | ✓ | ✓ | ✓ |
| window.location | × | ✓ | ✓ | ✓ |
| form GET提交 | × | ✓ | ✓ | ✓ |
| form POST提交 | × | Firefox: ✓ 其他: × |
✓ | 浏览器实现差异 |
| iframe加载 | × | × | ✓ | × |
| script标签 | × | × | ✓ | × |
| stylesheet | × | × | ✓ | × |
| fetch(credentials) | × | × | ✓ | × |
| XHR(withCredentials) | × | × | ✓ | × |
| prefetch | × | × | ✓ | × |
4. 安全攻击场景分析
4.1 CSRF攻击
GET请求CSRF:
- SameSite=Strict:完全防护
- SameSite=Lax/未设置:可被利用
- SameSite=None:可被利用
POST请求CSRF:
- 标准情况下:仅SameSite=None+Secure时可被利用
- 实际浏览器实现:
- Firefox:SameSite=Lax/未设置时可能被利用
- Chrome/Edge:严格遵循标准
4.2 JSONP劫持
依赖<script src>加载敏感数据:
- 仅当SameSite=None+Secure时可能成功
- 其他SameSite设置下无法携带Cookie
4.3 CORS配置不当
当服务器配置Access-Control-Allow-Credentials: true时:
- 仅SameSite=None+Secure时可通过AJAX/fetch跨域携带Cookie
- 需要配合
withCredentials或credentials: include设置
5. 防御建议
5.1 对于开发者
-
敏感Cookie设置:
- 优先使用SameSite=Strict
- 必要时使用SameSite=Lax
- 避免使用SameSite=None
-
Secure属性:
- 全站HTTPS环境下,始终设置Secure=true
- 避免Secure=false的敏感Cookie
-
HttpOnly属性:
- 防止XSS攻击获取Cookie
- 对会话标识等敏感Cookie应始终启用
5.2 对于安全测试人员
-
测试CSRF漏洞时:
- 检查Cookie的SameSite属性
- 测试不同浏览器下的行为差异
- 特别注意POST表单在Firefox中的特殊行为
-
测试JSONP/CORS时:
- 确认目标Cookie的SameSite=None+Secure
- 尝试多种跨域请求方法
- 检查服务器CORS头部配置
6. 浏览器兼容性注意事项
-
SameSite=None的特殊要求:
- 必须同时设置Secure
- 否则Chrome等浏览器会拒绝设置
-
未设置SameSite时的行为:
- 现代浏览器默认为Lax
- 但具体实现可能有细微差异
-
浏览器特定行为:
- Firefox对POST表单的处理较为宽松
- Chrome/Edge严格遵循标准
7. 实际测试案例
7.1 测试步骤
- 通过cookieSetting.html设置不同属性的Cookie
- 通过crossSite.html发起各种跨域请求
- 观察json.php的响应,判断Cookie是否被携带
7.2 关键测试代码
Cookie设置页面 (cookieSetting.html):
<form action="./getCookie.php" method="post">
<select name="samesite">
<option value="Strict">Strict</option>
<option value="Lax">Lax</option>
<option value="None">None</option>
<option value=" ">不设置</option>
</select>
<input type="checkbox" name="httponly">
<input type="checkbox" name="secure">
<select name="setcookie">
<option value="set">设置cookie</option>
<option value="">清除cookie</option>
</select>
</form>
后端处理 (getCookie.php):
setcookie('secret', '666666', [
'expires' => time() + 3600,
'path' => '/',
'domain' => 'test1.com',
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $simesite
]);
跨域测试页面 (crossSite.html):
<!-- 多种跨域请求方法 -->
<a href="https://test1.com/json.php">链接</a>
<form action="https://test1.com/json.php" method="post">
<button type="submit">POST表单</button>
</form>
<script src="https://test1.com/json.php"></script>
<script>
fetch('https://test1.com/json.php', {
credentials: 'include'
});
</script>
8. 总结
- SameSite属性是现代浏览器防御CSRF攻击的重要机制
- Secure属性是SameSite=None的必要条件
- 浏览器实现差异特别是Firefox对POST表单的处理需要特别注意
- 攻击面分析:
- CSRF:受SameSite影响较大,GET比POST更容易利用
- JSONP劫持:仅SameSite=None时可能
- CORS滥用:需要SameSite=None和服务器错误配置
- 防御策略:合理设置Cookie属性,理解浏览器安全机制,进行多浏览器兼容性测试