跳转到主要内容

CORS

本文约需 2 分钟阅读

CORS (Cross-Origin Resource Sharing,跨源资源共享) 是浏览器向不同源 (域名、端口、协议的组合) 的服务器发送请求时的访问控制机制。它于 2014 年由 W3C 发布为推荐标准,目前所有主流浏览器都已实现。如今,Web 应用将前端和后端运行在不同域名上的架构已经普及,正确理解和配置 CORS 已成为 Web 开发者的必备技能。它也是与 CSRFXSS 密切相关的安全机制。

与同源策略 (SOP) 的关系

要理解 CORS,首先需要了解同源策略 (Same-Origin Policy)。SOP 是 1995 年在 Netscape Navigator 2.0 中引入的浏览器安全模型,其约束是「从某个源加载的脚本无法访问另一个源的资源」。

源的构成要素:
https://example.com:443/path
协议: https主机: example.com端口: 443
只有当这三者全部一致时才算「同源」。路径无关。
https://example.com/page1 → https://example.com/page2 (相同)
https://example.com → http://example.com (协议不同)
https://example.com → https://api.example.com (主机不同)
https://example.com → https://example.com:8080 (端口不同)

如果没有 SOP,恶意网站调用银行网站的 API 获取用户账户信息这类攻击就很容易得逞。CORS 是用于安全地放宽这一 SOP 约束的机制。通过服务器明确声明「允许来自此源的请求」,使合法的跨源通信成为可能。

预检请求 (OPTIONS) 的机制

在发送满足特定条件的跨源请求之前,浏览器会使用 OPTIONS 方法发送「预检请求」。这是向服务器事先确认「是否接受此请求?」的机制。

浏览器发送 OPTIONS服务器返回许可头浏览器确认许可发送原本的请求服务器返回响应

触发预检的条件包括使用 PUT / DELETE / PATCH 方法、Content-Type: application/json 等自定义头的发送、认证信息 (Cookie) 的发送等。如果 GET 请求没有自定义头,则被视为「简单请求」,预检会被省略。

主要的 CORS 响应头

作用注意事项
Access-Control-Allow-Origin指定允许的源通配符 (*) 不可与带认证信息的请求并用
Access-Control-Allow-Methods列举允许的 HTTP 方法在预检响应中返回
Access-Control-Allow-Headers列举允许的请求头明确列出 Authorization 等自定义头
Access-Control-Allow-Credentials允许发送 Cookie 等认证信息为 true 时,Allow-Origin 不能使用 *
Access-Control-Max-Age预检结果的缓存秒数过长会导致配置变更的生效延迟

常见的错误配置及其风险

Access-Control-Allow-Origin: *

允许所有源的设置。对公开 API 是合适的,但若配置在需要认证的 API 上,恶意网站就能获取用户数据。由于无法与 Credentials 并用,在使用 Cookie 认证的 API 上无法生效。

对 Origin 头的无校验反射

将请求的 Origin 头的值原样返回到 Allow-Origin 的实现。实质上等同于允许所有源,但由于可以与 Credentials: true 并用,比 * 更危险。

允许 null 源

设置 Access-Control-Allow-Origin: null 会允许来自沙箱 iframe 或本地文件的请求。会被攻击者用于从 iframe 内调用 API 的攻击。

CORS 与 CSRF 的关系

CORS 和 CSRF 常被混淆,但二者防御的对象不同。CORS 是浏览器控制响应读取的机制,对请求的发送本身 (在简单请求的情况下) 并不会拦截。也就是说,即使正确配置了 CORS,也可能无法阻止 CSRF 攻击发出的请求。CSRF 防护需要令牌方式或 SameSite Cookie 属性等另外的防御层。与 CSPSSL/TLS 相结合的多层防御很重要。

在使用 API 密钥 的服务中,CORS 的配置错误有时也会导致 API 密钥泄露。也请一并参阅 浏览器扩展程序的安全API 密钥管理的最佳实践初创公司的安全检查清单Web API 安全相关书籍 (Amazon)推荐用来学习实现模式。

相关术语

这篇文章对您有帮助吗?

XHatena