绕过SameSite Cookie限制
翻译
原文:https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions
- name: 翻译
desc: 原文:https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions
bgColor: '#F0DFB1'
textColor: 'green'
2
3
4
# 绕过SameSite Cookie限制
SameSite 是一种浏览器安全机制,用于确定何时将网站的 Cookie 包含在来自其他网站的请求中。SameSite Cookie 限制提供了部分保护,以抵御各种跨站点攻击,其中包括 CSRF、跨站点泄漏和某些CORS (opens new window)攻击。
自 2021 年起,如果发布 Cookie 的网站没有明确设置自己的限制级别,则 Chrome 会默认应用Lax
(宽松)级别的 SameSite 限制。这是一个拟议的标准,我们希望其他主流浏览器将来也会采用这种行为。因此,必须牢牢掌握这些限制的工作原理,以及如何绕过它们,以便深入测试跨站点攻击向量。
在本节中,我们将首先介绍 SameSite 机制的工作原理,并阐明一些相关术语。然后,我们将介绍一些最常见的、绕过这些限制的方法,在初步评估为安全的网站上,发起 CSRF 和其他跨站点攻击。
# 1位于SameSite Cookie上下文中的site是什么?
在 SameSite Cookie 限制的上下文中,site 被定义为顶级域(TLD),通常是.com
或.net
之类的域名,然后再加上域名的一个附加级别。这通常被称为 TLD+1。
在确定请求是否为同一站点时,还会将 URL 协议考虑在内。这意味着从http://app.example.com
到https://app.example.com
的链接被大多数浏览器视为跨站点链接。
笔记
你可能会遇到术语 “有效顶级域”(eTLD)。这只是一种解释 保留多部分后缀 的方法,这些后缀在实践中被视为顶级域,例如.co.uk
。
# 2site和origin之间有什么区别?
site(站)和 origin(源)之间的区别在于它们的范围;一个 site 涵盖多个域名,而一个 origin 仅包含一个域名。尽管它们密切相关,但重要的是不要互换使用这两个术语,因为将两者混为一谈可能会产生严重的安全影响。
如果两个 URL 共享完全相同的协议、域名和端口,则认为它们具有相同的来源。但请注意,端口通常是从协议中推断出来的。
从这个例子中可以看出,术语 “site” 没有那么具体,因为它只说明了协议和域名的最后一部分。至关重要的是,这意味着跨域请求仍然可以是同一站点的,但不能相反。
请求起点 | 请求终点 | 同站(site)? | 同源(origin)? |
---|---|---|---|
https://example.com | https://example.com | Yes | Yes |
https://app.example.com | https://intranet.example.com | Yes | No:域名不匹配 |
https://example.com | https://example.com:8080 | Yes | No:端口不匹配 |
https://example.com | https://example.co.uk | No:eTLD不匹配 | No:域名不匹配 |
https://example.com | http://example.com | No:协议不匹配 | No:协议不匹配 |
这是一个重要的区别,因为这意味着任何支持 JavaScript 执行的漏洞都可能被滥用,以绕过属于同一站点的其他域上的基于 site 的防御。我们将会在稍后的实验室中看到一个示例。
# 3SameSite如何工作?
在引入 SameSite 机制之前,浏览器会向发出请求的每个域发送 Cookie,即使该请求是由不相关的第三方网站触发的。SameSite 的工作原理是——允许 浏览器和网站所有者 限制跨站点请求(如果有的话)应该包含哪些特定的 Cookie。这有助于减少用户遭受 CSRF 攻击的风险,CSRF 攻击会诱使受害者的浏览器发出请求,从而在易受攻击的网站上触发有害操作。由于这些请求通常需要一个 与受害者的身份验证会话相关联的 Cookie,因此如果浏览器不包含此 Cookie,则攻击将失败。
目前,所有主流浏览器都支持以下 SameSite 限制级别:
开发人员可以为他们设置的每个 Cookie 手动配置限制级别,从而更好地控制何时使用这些 Cookie。要做到这一点,他们只需要在Set-Cookie
响应标头中包含SameSite
属性以及它们的首选值:
Set-Cookie: session=0F8tgdOhi9ynR1M9wa3ODa; SameSite=Strict
尽管这提供了一些针对 CSRF 攻击的保护,但这些限制都不能提供绝对的保障,稍后我们将使用故意易受攻击的交互式实验室演示这一点。
笔记
如果发布 Cookie 的网站没有明确设置 SameSite 属性,则 Chrome 会默认应用Lax
(宽松)级别的 SameSite 限制。这意味着 Cookie 仅在满足特定条件的跨站点请求中发送,即使开发人员从未配置过这种行为 也是如此。由于这是一个拟议的新标准,我们希望其他主流浏览器将来也会采用这种行为。
# 3.1Strict(严格)
如果 Cookie 设置了SameSite=Strict
属性,浏览器将不会在任何跨站点请求中发送它。简单来讲,这意味着如果请求的目标网站 与 当前浏览器地址栏中显示的网址不匹配,则不会在请求中包含 Cookie。
建议在设置 Cookie 时使用此功能,使持有者能够安全地修改数据或执行其他敏感操作。例如,访问 仅对经过身份验证的用户 可用的特定页面。
尽管这是最安全的选项,但在需要跨站点功能的情况下,它可能会对用户体验产生负面影响。
# 3.1.1相关实验室
- 使用站内小工具绕过SameSite Strict限制 (opens new window)LAB
- 通过易受攻击的同级域绕过SameSite Strict限制 (opens new window)LAB
# 3.2Lax(宽松)
Lax
级别的 SameSite 限制意味着浏览器将在跨站点请求中发送 Cookie,但前提是同时满足以下两个条件:
- 请求使用
GET
方法。 - 该请求是由用户的顶级导航发起的(例如单击链接)。
例如,这意味着 Cookie 不会被包含在跨站点POST
请求中。由于POST
请求通常用于执行修改数据 或 状态的操作(最佳攻击实践),因此它们更有可能成为 CSRF 攻击的目标。
同样,Cookie 不会被包含在后台请求中,例如由 script、iframe 或对图像和其他资源的引用而发起的请求。
# 3.2.1相关实验室
# 3.3None(禁用)
如果 Cookie 设置为SameSite=None
属性,则无论浏览器如何,这都会完全有效地禁用 SameSite 限制。因此,浏览器将在所有请求中包含此 Cookie,并将其发送到目标站点,即使是由完全不相关的第三方网站触发的请求。
除 Chrome 外,如果在设置 Cookie 时未提供SameSite
属性,这将是其他主流浏览器使用的默认行为(None)。
禁用 SameSite 是有正当理由的,例如当 Cookie 打算在第三方上下文中使用,并且不授予持有者 访问任何敏感数据或功能 的权限时。跟踪 Cookie 就是一个典型的例子。
如果你遇到SameSite=None
或没有明确限制的 Cookie 时,则值得调查它是否有用。当 Chrome 首次采用 “默认Lax(宽松)” 这一行为时,这可能会产生副作用,例如破坏许多现有 Web 功能。一些网站选择简单地禁用对所有 Cookie 的 SameSite 限制,包括潜在的敏感 Cookie,作为一种快速解决副作用的方法。
当设置 Cookie 为SameSite=None
时,网站还必须包含Secure
属性,以确保 Cookie 仅通过 HTTPS 的加密消息形式发送。否则,浏览器将拒绝该 Cookie,并且不会对其进行设置。
Set-Cookie: trackingId=0F8tgdOhi9ynR1M9wa3ODa; SameSite=None; Secure
# 4使用GET请求绕过SameSite Lax限制
在实践中,对于给定端点接收到的GET
或POST
请求,服务器并不总是会显得很挑剔,即使是那些期望表单提交的端点。如果他们同时对其会话 Cookie 使用Lax
限制,无论是明确指定该值,还是由于浏览器默认设置该值,你仍然可以通过从受害者的浏览器引发GET
请求来执行 CSRF 攻击。
只要请求涉及顶级导航,浏览器仍将包含受害者的会话 Cookie。以下是发起此类攻击的最简单方法之一:
<script>
document.location = 'https://vulnerable-website.com/account/transfer-payment?recipient=hacker&amount=1000000';
</script>
2
3
即使不允许常规的GET
请求,一些框架也会提供相应的手段,可用于覆盖原来的请求方法。例如,Symfony 支持表单中的_method
参数,该参数的优先级 大于 常规的路由方法:
<form action="https://vulnerable-website.com/account/transfer-payment" method="POST">
<input type="hidden" name="_method" value="GET">
<input type="hidden" name="recipient" value="hacker">
<input type="hidden" name="amount" value="1000000">
</form>
2
3
4
5
其他框架支持各种类似的参数。
- name: 实验室-从业者
desc: SameSite Lax绕过-覆盖请求方法 >>
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/csrf/bypassing-samesite-restrictions/lab-samesite-lax-bypass-via-method-override
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 5使用站内小工具绕过SameSite限制
如果使用SameSite=Strict
属性设置 Cookie,浏览器将不会在任何跨站点请求中包含 Cookie。如果你能在同一站点中 找到一个导致二次请求的小工具,则可以绕过此限制。
一种可能的小工具是客户端重定向,它使用攻击者可控制的输入(如 URL 参数)动态构造重定向目标。有关一些示例,请参阅我们关于基于DOM的开放重定向 (opens new window)的资料。
就浏览器而言,这些客户端重定向根本不是真正的重定向;生成的请求仅被视为普通的独立请求。最重要的是,这是一个相同站点的请求,因此,该请求中将包含 与当前站点相关的所有 Cookie,无论其是否存在任何限制。
如果你可以操纵此小工具,以引发恶意的二次请求,则可以完全绕过任何 SameSite Cookie 限制。
- name: 实验室-从业者
desc: SameSite Strict绕过-客户端重定向 >>
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/csrf/bypassing-samesite-restrictions/lab-samesite-strict-bypass-via-client-side-redirect
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 6通过易受攻击的同级域绕过SameSite限制
无论你是在测试他人的网站,还是试图保护自己的网站,都必须记住,即使请求是跨域发出的,该请求仍然可以是同一站点(同源策略 和 同站策略的区别)。
确保彻底审核所有可用的攻击面,包括任何同级域。特别是,使你能够引发任何二次请求的漏洞(如XSS (opens new window))可能会完全破坏基于站点的防御,从而使站点的所有域都暴露在跨站点攻击之下。
除了经典的 CSRF 之外,不要忘记,如果目标网站支持WebSockets (opens new window),则该功能可能容易受到WebSocket跨站劫持(CSWSH) (opens new window)的攻击,CSWSH 本质上只是针对 WebSocket 握手的CSRF (opens new window)攻击。有关更多详细信息,请参阅有关WebSocket漏洞 (opens new window)的主题。
- name: 实验室-从业者
desc: SameSite Strict绕过-易受攻击的同级域 >>
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/csrf/bypassing-samesite-restrictions/lab-samesite-strict-bypass-via-sibling-domain
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6
# 7使用新发布的Cookie绕过SameSite Lax限制
具有 SameSite 限制且级别为Lax
的 Cookie,通常不会在任何跨站点POST
请求中发送,但也有一些例外。
如前所述,如果网站在设置 Cookie 时不包含SameSite
属性,则默认情况下,Chrome 会自动应用Lax
级别的限制。但是,为了避免破坏单点登录(SSO)机制,它实际上不会在顶级POST
请求的前 120 秒内强制实施这些限制。因此,有一个两分钟的窗口期,用户可能容易受到跨站点攻击。
笔记
此两分钟窗口不适用于显式设置SameSite=Lax
属性的 Cookie。
尝试在这个定时的短窗口内进行攻击,有点不切实际。另一方面,如果你能够在网站上找到一个小工具,使你能够强制向受害者发送一个新的会话 Cookie,则可以在后续的主要攻击之前,抢先刷新他们的 Cookie。例如,完成基于 OAuth 的登录流可能会导致每次都生成一个新会话,因为 OAuth 服务不一定知道用户是否仍在尝试登录到目标站点。
要在受害者不必再次手动登录的情况下触发 Cookie 刷新,你需要使用顶级导航,以确保其包含与当前 OAuth 会话相关联的 Cookie。这带来了额外的挑战,因为你需要将用户重定向到你的站点,以便你可以发起 CSRF 攻击。
或者,你可以从一个新的选项卡触发 Cookie 刷新,以便浏览器 在你能够进行最终攻击之前 不会离开页面。这种方法的一个小阻碍是,浏览器会阻止选项卡弹出,除非它们是通过手动交互打开的。例如,浏览器默认会阻止以下窗口弹出:
window.open('https://vulnerable-website.com/login/sso');
要解决这个问题,你可以将语句包装在onclick
事件处理程序中,如下所示:
window.onclick = () => {
window.open('https://vulnerable-website.com/login/sso');
}
2
3
这样一来,仅在用户单击页面上的某个位置时,window.open()
方法才会被调用。
- name: 实验室-从业者
desc: SameSite Lax绕过-Cookie刷新 >>
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/csrf/bypassing-samesite-restrictions/lab-samesite-strict-bypass-via-cookie-refresh
bgColor: '#001350'
textColor: '#4cc1ff'
2
3
4
5
6