CORS和Access-Control-Allow-Origin响应标头
翻译
原文:https://portswigger.net/web-security/cors/access-control-allow-origin
- name: 翻译
desc: 原文:https://portswigger.net/web-security/cors/access-control-allow-origin
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# CORS 和 Access-Control-Allow-Origin 响应标头
在本节中,我们将解释 CORS 的Access-Control-Allow-Origin
标头是什么,以及它如何构成 CORS 实现的一部分。
跨域资源共享 (opens new window)规范通过使用 HTTP 标头的集合,为从一个网站域 到 另一个网站域的 HTTP 请求提供了对同源策略 (opens new window)的受控放宽。浏览器根据这些标头指令,将被允许访问对跨域请求的响应。
# 1什么是Access-Control-Allow-Origin响应头?
当一个网站 接收到 源自另一个网站的请求时,Access-Control-Allow-Origin
标头会被包含在响应中,并标识请求的允许来源。Web 浏览器将Access-Control-Allow-Origin
的值 与 源请求网站进行比较,如果它们匹配的话,将使源网站允许访问响应。
# 2实现简单的跨域资源共享
跨域资源共享(CORS)标准规定了在 Web 服务器和浏览器之间交换的标头内容,以限制源域之外的 Web 资源请求来源。CORS 规范标识了一组协议标头,其中Access-Control-Allow-Origin
是最重要的。当网站请求跨域资源时,服务器会返回此标头,浏览器会添加Origin
标头。
例如,假设来源为normal-website.com
的网站产生以下跨域请求:
GET /data HTTP/1.1
Host: robust-website.com
Origin : https://normal-website.com
2
3
robust-website.com
上的服务器返回以下响应:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
2
3
对于在normal-website.com
上运行的代码,浏览器将允许其访问响应,因为来源匹配。
Access-Control-Allow-Origin
的规范允许多个来源,也允许值null
或通配符*
。但是,没有浏览器支持多个来源,并且对通配符*
的使用有限制。
# 3跨域资源请求中的凭据处理
跨域资源请求的默认行为是,在没有 Cookie 和Authorization
标头等凭据的情况下传递请求。但是,通过将 CORS Access-Control-Allow-Credentials
标头设置为true
,跨域服务器将允许 在向其传递凭证时读取响应。现在,如果请求网站使用 JavaScript 声明它正在发送请求的 Cookie:
GET /data HTTP/1.1
Host: robust-website.com
...
Origin: https://normal-website.com
Cookie: JSESSIONID=<value>
2
3
4
5
而对请求的响应是:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: true
2
3
4
那么,浏览器将允许请求网站读取响应,因为Access-Control-Allow-Credentials
响应标头设置为true
。否则,浏览器将不允许其访问响应。
# 4使用通配符放宽 CORS 规范
标头Access-Control-Allow-Origin
支持通配符。例如:
Access-Control-Allow-Origin: *
笔记
请注意,通配符不能在任何其他值中使用。例如,以下标头无效:
Access-Control-Allow-Origin: https://*.normal-website.com
幸运的是,从安全的角度来看,通配符的使用在规范中受到了限制,因为你无法将通配符与凭据(authentication凭据、Cookie 或客户端证书)的跨域传输结合使用。一旦两者结合使用,跨域服务器的响应形式就像:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
2
这是不允许的,因为这将是非常不安全的,这会向所有人公开 目标站点上任何经过身份验证的内容。
鉴于这些约束,一些 Web 服务器会根据客户端指定的源,来动态创建Access-Control-Allow-Origin
标头。这是约束 CORS 的不安全解决方案。稍后我们将向你展示如何利用这一点 (opens new window)。
# 5预检查
(((译者加:有关于 “HTTP CORS OPTIONS预检请求” 的相关知识,可参阅这两篇文章:文章1 (opens new window)、文章2 (opens new window))))
预检已被添加到 CORS 规范中,以保护遗留资源免受 CORS 允许的扩展请求选项的影响。在某些情况下,当跨域请求中包含非标准 HTTP 方法或标头时,根据 CORS 协议,在允许和进行跨域请求之前,会先使用OPTIONS
方法对 “是否允许这些方法和标头” 进行初始检查,这称为预检查。除了受信任的源之外,服务器还会返回一个允许的方法列表,浏览器根据该列表,检查 用于请求网站的方法 是否被允许。
例如,这是一个预检请求,它试图将PUT
方法与名为Special-Request-Head
的自定义请求标头一起使用:
OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header
2
3
4
5
6
服务器可能会返回如下响应:
HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240
2
3
4
5
6
7
此响应列出了允许的方法(PUT
、POST
和OPTIONS
)和允许的请求标头(Special-Request-Header
)。在这种特定情况下,跨域服务器还允许其发送凭据,并且Access-Control-Max-Age
标头定义了 缓存预检响应 的最大重发时间范围。如果请求的方法和标头被允许(如本例所示),则浏览器将以常规方式处理跨域请求。
值得一提的是,预检会向跨域请求添加额外的 HTTP 请求往返,因此会增加浏览开销。
# 6CORS是否能抵御CSRF?
CORS 不提供针对跨站请求伪造(CSRF) (opens new window)攻击的保护,这是一个常见的误解。
CORS 是对同源策略的受控放宽,因此配置不当的 CORS 实际上可能会增加 CSRF 攻击的可能性或加剧其影响。
有多种方法可以在不使用 CORS 的情况下执行 CSRF 攻击,这包括简单的 HTML 表单和跨域资源包含。