前端攻防之解读浏览器同源策略
字数 2232 2025-08-07 08:22:20

浏览器同源策略全面解析与安全实践

0x0 前言

同源策略(Same Origin Policy, SOP)是浏览器安全的核心机制,但许多开发者对其理解仅停留在表面。本文将从定义、机制、实际案例到绕过方法,全面剖析同源策略及其安全影响。

0x1 同源策略定义

官方定义

  • Firefox文档: 同源策略是一种网络浏览器的安全机制,防止不同网站相互攻击
  • RFC 6454: 限制从一个源加载的文档/脚本如何与另一个源的资源交互

同源判定标准

两个URL同源需同时满足以下三个条件:

  1. 协议相同 (http/https/file等)
  2. 端口相同
  3. 主机名相同

示例分析:

URL 结果 原因
http://store.company.com/dir2/other.html 同源 仅路径不同
https://store.company.com/secure.html 不同源 协议不同
http://store.company.com:81/dir/etc.html 不同源 端口不同
http://news.company.com/dir/other.html 不同源 主机不同

0x2 同源策略的意义

没有同源策略的后果:

  • 恶意网站可读取用户在其他网站(GMail、Facebook等)的敏感数据
  • 用户浏览行为毫无隐私和安全保障
  • 跨站脚本攻击(XSS)的危害将无限放大

0x3 同源策略机制

应用场景

浏览器在以下交互中实施来源检查:

  1. DOM访问限制

    • 页面无法访问不同源iframe的内容
    • 限制跨域JavaScript对DOM的操作
  2. 数据存储隔离

    • LocalStorage、IndexDB、Cookie按源隔离
    • 禁止跨域读取敏感数据
  3. 网络请求控制

    • 限制XMLHttpRequest跨域请求
    • 规范fetch API的跨域行为

交互分类

  1. 跨域写操作:通常允许(如链接、重定向、表单提交)
  2. 跨域资源嵌入:通常允许(如脚本、图片、CSS、iframe)
  3. 跨域读操作:通常禁止

0x4 关键示例分析

4.1 document.domain误区

常见误区

  1. 认为可以任意设置domain值为一级子域名
  2. 认为单方面设置document.domain即可跨域

正确理解

  • 只能设置为当前域或其上级域
  • 必须双方同时设置相同document.domain
  • 设置后端口会被置为null,需特别注意

实验代码

<!-- xq17.com -->
<script>document.domain = 'xq17.com'; var flag= "flag:{xq17.com}";</script>

<!-- a.xq17.com -->
<script>
document.domain = 'xq17.com';
function load(){ console.log(frame.contentWindow.flag); }
</script>
<iframe src="http://xq17.com/" id="frame"></iframe>

4.2 跨域Cookie读取

Cookie共享规则

  1. 不指定domain时,Cookie仅对当前域有效
  2. 指定domain为.xq17.com时,所有子域可共享

Flask示例

@app.route("/set_cookie")
def set_cookie():
    resp = Response("success")
    # 仅当前域有效
    resp.set_cookie('flag', 'key pass', path='/')
    # 所有子域共享
    resp.set_cookie('flag', 'key pass', path='/', domain='.xq17.com')
    return resp

4.3 window.name跨域技术

特性

  • 无视同源策略,窗口生命周期内所有页面共享
  • 可用于跨域数据传递

利用方法

<!-- b.xq17.com/data.html -->
<script>window.name = "敏感数据";</script>

<!-- a.xq17.com/getData.html -->
<script>
function getData(){
    var iframe = document.getElementById('proxy');
    iframe.src = 'a.xq17.com/a.html'; // 切换为同源
    iframe.onload = function(){
        console.log(iframe.contentWindow.name); // 获取数据
    };
}
</script>
<iframe id="proxy" src="http://b.xq17.com/data.html" onload="getData()"></iframe>

4.4 安全利用思路

  1. 检查document.domain设置不当导致的跨域
  2. 寻找window.name中的敏感信息
  3. 探测共享Cookie配置不当的子域
  4. 利用postMessage实现跨域通信

0x5 主流跨域方法

5.1 CORS(跨源资源共享)

安全风险

# 危险配置:允许任意源携带凭证
Access-Control-Allow-Origin $http_origin;
Access-Control-Allow-Credentials true;

Flask示例

@app.route("/credential")
def get_credential():
    resp = make_response("敏感数据")
    origin = request.headers.get('Origin')
    resp.headers['Access-Control-Allow-Origin'] = origin
    resp.headers['Access-Control-Allow-Credentials'] = 'true'
    return resp

SameSite影响

  • Lax模式(默认)下,跨站AJAX请求不会携带Cookie
  • 缓解了CORS漏洞的危害

5.2 JSONP跨域

原理

<script>
function exp(data){ console.log(data); }
</script>
<script src="http://b.xq17.com/jsonp?callback=exp"></script>

安全风险

  1. 仅支持GET请求
  2. 回调函数注入导致XSS

防护措施

  1. 设置Content-Type: application/javascript
  2. 对输出进行HTML编码

5.3 postMessage跨域

安全用法

// 发送方
targetWindow.postMessage(message, 'https://trusted.com');

// 接收方
window.addEventListener('message', (event) => {
    if(event.origin !== 'https://trusted.com') return;
    console.log(event.data);
});

常见漏洞

  1. 目标origin设置为*
  2. 接收方未验证event.origin
  3. 直接使用innerHTML导致XSS

0x6 SameSite机制

属性值对比

描述 适用场景
Strict 仅限第一方上下文 高敏感操作
Lax(默认) 允许顶级导航GET请求 平衡安全与可用性
None 允许所有跨站请求 必须配合Secure属性

浏览器兼容性

  • Chrome 51+、Firefox 60+支持
  • Chrome 80+默认Lax
  • Firefox 96+默认Lax

eTLD+1规则

  • 站(Site)定义为有效顶级域名(eTLD)+1
  • 示例:
    • a.web.dev和b.web.dev → 同站
    • a.github.io和b.github.io → 跨站

0x7 总结

同源策略是Web安全的基石,但各种跨域技术带来了复杂的安全考量:

  1. CORS配置不当会导致敏感数据泄露
  2. JSONP可能引入XSS漏洞
  3. postMessage需严格验证origin
  4. SameSite机制有效缓解了CSRF和部分CORS风险

安全建议:

  • 严格校验跨域请求的Origin头
  • 避免使用不安全的跨域技术(document.domain)
  • 关键Cookie设置SameSite=Strict
  • 对所有用户输入进行编码和验证

0x8 参考资源

  1. MDN Same-origin policy
  2. RFC 6454
  3. SameSite Cookies Explained
  4. PostMessage Security
浏览器同源策略全面解析与安全实践 0x0 前言 同源策略(Same Origin Policy, SOP)是浏览器安全的核心机制,但许多开发者对其理解仅停留在表面。本文将从定义、机制、实际案例到绕过方法,全面剖析同源策略及其安全影响。 0x1 同源策略定义 官方定义 Firefox文档 : 同源策略是一种网络浏览器的安全机制,防止不同网站相互攻击 RFC 6454 : 限制从一个源加载的文档/脚本如何与另一个源的资源交互 同源判定标准 两个URL同源需同时满足以下三个条件: 协议相同 (http/https/file等) 端口相同 主机名相同 示例分析: | URL | 结果 | 原因 | |------|------|------| | http://store.company.com/dir2/other.html | 同源 | 仅路径不同 | | https://store.company.com/secure.html | 不同源 | 协议不同 | | http://store.company.com:81/dir/etc.html | 不同源 | 端口不同 | | http://news.company.com/dir/other.html | 不同源 | 主机不同 | 0x2 同源策略的意义 没有同源策略的后果: 恶意网站可读取用户在其他网站(GMail、Facebook等)的敏感数据 用户浏览行为毫无隐私和安全保障 跨站脚本攻击(XSS)的危害将无限放大 0x3 同源策略机制 应用场景 浏览器在以下交互中实施来源检查: DOM访问限制 页面无法访问不同源iframe的内容 限制跨域JavaScript对DOM的操作 数据存储隔离 LocalStorage、IndexDB、Cookie按源隔离 禁止跨域读取敏感数据 网络请求控制 限制XMLHttpRequest跨域请求 规范fetch API的跨域行为 交互分类 跨域写操作 :通常允许(如链接、重定向、表单提交) 跨域资源嵌入 :通常允许(如脚本、图片、CSS、iframe) 跨域读操作 :通常禁止 0x4 关键示例分析 4.1 document.domain误区 常见误区 : 认为可以任意设置domain值为一级子域名 认为单方面设置document.domain即可跨域 正确理解 : 只能设置为当前域或其上级域 必须双方同时设置相同document.domain 设置后端口会被置为null,需特别注意 实验代码 : 4.2 跨域Cookie读取 Cookie共享规则 : 不指定domain时,Cookie仅对当前域有效 指定domain为 .xq17.com 时,所有子域可共享 Flask示例 : 4.3 window.name跨域技术 特性 : 无视同源策略,窗口生命周期内所有页面共享 可用于跨域数据传递 利用方法 : 4.4 安全利用思路 检查document.domain设置不当导致的跨域 寻找window.name中的敏感信息 探测共享Cookie配置不当的子域 利用postMessage实现跨域通信 0x5 主流跨域方法 5.1 CORS(跨源资源共享) 安全风险 : Flask示例 : SameSite影响 : Lax模式(默认)下,跨站AJAX请求不会携带Cookie 缓解了CORS漏洞的危害 5.2 JSONP跨域 原理 : 安全风险 : 仅支持GET请求 回调函数注入导致XSS 防护措施 : 设置Content-Type: application/javascript 对输出进行HTML编码 5.3 postMessage跨域 安全用法 : 常见漏洞 : 目标origin设置为 * 接收方未验证event.origin 直接使用innerHTML导致XSS 0x6 SameSite机制 属性值对比 | 值 | 描述 | 适用场景 | |----|------|----------| | Strict | 仅限第一方上下文 | 高敏感操作 | | Lax(默认) | 允许顶级导航GET请求 | 平衡安全与可用性 | | None | 允许所有跨站请求 | 必须配合Secure属性 | 浏览器兼容性 Chrome 51+、Firefox 60+支持 Chrome 80+默认Lax Firefox 96+默认Lax eTLD+1规则 站(Site)定义为有效顶级域名(eTLD)+1 示例: a.web.dev和b.web.dev → 同站 a.github.io和b.github.io → 跨站 0x7 总结 同源策略是Web安全的基石,但各种跨域技术带来了复杂的安全考量: CORS配置不当会导致敏感数据泄露 JSONP可能引入XSS漏洞 postMessage需严格验证origin SameSite机制有效缓解了CSRF和部分CORS风险 安全建议: 严格校验跨域请求的Origin头 避免使用不安全的跨域技术(document.domain) 关键Cookie设置SameSite=Strict 对所有用户输入进行编码和验证 0x8 参考资源 MDN Same-origin policy RFC 6454 SameSite Cookies Explained PostMessage Security