欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[翻译]使用同站点cookies阻止跨站攻击

[翻译]使用同站点cookies阻止跨站攻击




Dropbox采用传统的跨站攻击防御手段,但我们也使用相同的网站Cookie作为对新型浏览器的深度防御手段。在这篇文章中,我们描述了如何在Dropbox上推出基于同站点cookies的防御,并提供了一些关于如何在您的网站上执行相同操作的指导。


背景

最近,IETF(国际互联网工程任务组)发布了一个介绍同站点cookies的新版RFC。与传统Cookie不同,浏览器不会在跨站点请求中发送同站点cookies Dropbox最近开始使用同站点cookies技术来防止CSRF攻击和跨站点信息泄露。有此我们得出结论,同站点cookies技术是减少网站遭受攻击概率的便捷方式。


跨站请求

网络上的许多攻击涉及跨站点请求,包括众所周知的跨站请求伪造(CSRF)攻击。这种攻击可以诱骗让受害者的浏览器对受信任的网站进行无意的请求。由于用户信任Dropbox并在Dropbox上保存有很多敏感的数据,因此我们对于这类攻击尽可能的强化防显得御至关重要。

什么是CSRF攻击?举个栗子,让我们假装Dropbox天真地不会防范CSRF攻击。受害者访问攻击者控制的网站时,袭击开始,如www.evil.com。然后这个网站返回带有恶意加载数据的页面。浏览器将会执行这些恶意加载数据,它会发起如https://dropbox.com/cmd/delete的请求并尝试删除用户数据。

一个假象的针对DropboxCSRF攻击


经典的针对CSRF的防御方法是引入随机值令牌(称为CSRF令牌),并将其值存储在cookie中,称为csrf_cookie,在第一页加载。浏览器在每次不安全请求(POSTS)中发送CSRF令牌作为请求参数。然后,服务器将csrf_cookie的值与请求参数进行比较,如果这些值不匹配,则会抛出一个CSRF错误。

即使网站具有CSRF防御功能,也可能容易受到跨站信息泄露攻击(如跨站搜索攻击和JSON劫持)。 例如,假设www.dropbox.com有一个AJAX路由/ get_files / get_filesGET请求将获取所有登录用户的文件名, 响应的大小则可能引起一些侧面信息(例如用户的Dropbox中有多少文件)的泄漏。

我们现在来描述一下如何设计和使用同站点cookies技术来防御针对Dropbox的跨站点攻击。

 

设计

为了可靠性和安全性,我们对同站点cookies保护方案的设计应具有以下要求:

l  CSRF防御:提供的防御应等同于我们现有的CSRF防御:所有POST请求(默认情况下)必须是同站点请求,因为它们状态随时发生变化。 GET请求不需要任何CSRF保护,但可能仍需要对不同类型的跨站漏洞负责(请参阅下一个要求)。

l  跨站点信息泄漏防御:AJAX 中的GET请求应该是同站点的,因为它们是许多跨站点信息泄漏漏洞的源头。

l  可用性:我们的设计的保护手段应该经过仔细推敲的并容易复原。 我们仍然会保持现有的CSRF防御,因为同站点Cookie保护技术只是一种防御加固手段。 此外,在实行该技术时,我们不应该破坏有效的跨站点GET请求(例如通过电子邮件共享的Dropbox链接)的现有行为。

l  灵活性:我们的设计应该是可扩展的,以允许在各种请求类型和路由上进行跨站防御,而不仅仅是POST请求和AJAX GET请求。

 

通过将SameSite属性设置为两个值(严格或松散)中之一,可以使Cookie变为同站点的。 严格情况下,浏览器不会在任何跨站点请求上发送同站点cookie。当不那么严格时,浏览器只阻止在“不安全”请求(POST)中发送同站点cookie,但将允许“安全”请求(GET)发送。

假设Dropbox存储两个cookie:一个session_cookie和一个csrf_cookie(我们正在简化)。

此外,Dropbox站点上的https://dropbox.com/ajax_loginPOST请求将输用户的凭据作为输入,然后允许用户登录(或同样地,写入session_cookie)。Dropbox在页面上也有许多“共享链接”,格式为https://dropbox.com/sh/.../filename 用户可以通过电子邮件分享这些链接,并限制对这些链接的访问。


在对如何向Dropbox添加同站点Cookie保护进行头脑风暴时,我们提出了以下天真的设计,但很快就弄清楚他们有缺陷:

l  将强制登录模式中的SameSite属性添加到session_cookie中。这使得所有请求都登录到同一站点,并针对所有经过身份验证的用户的CSRF和交叉信息泄漏进行辩护。 不幸的是,在用户通过电子邮件共享的链接对Dropbox 进行访问的情况下,这可能是有问题的。 上述情况下,通过身份验证的用户的跨站GET请求可能与预期不同,因为浏览器将不会发送该cookie

候选设计方案1Dropbox在强制登录模式下给会话cookie添加同站点属性

方案1并不理想,因为好的跨站GET请求将要求用户重新登录(即使该用户已经登录)


l  在松散模式而非强制模式下使用session_cookie。如前所述,这只会提供基本的CSRF保护,并且也不能防御交叉源信息泄漏攻击(如跨站搜索攻击和使用AJAX GET请求的JSON劫持)。此外,它比我们已有的CSRF保护更弱,因为它不为未经身份验证的用户提供保护(例如,它不提供对登录CSRF攻击的防御)。

候选设计方案2Dropbox在松散登录模式下给会话cookie添加同站点属性。这样CSRF防御只能用于认证请求,例如第一个登录请求可能是跨站请求。

l  在强制登录模式下,将CSRF cookiecsrf_cookie)作为同站点cookie。然而,这使得逐步发现及应对意外故障变得更加困难。此外,为避免会话固定我们会以加密方式将CSRF令牌绑定到session_cookie上,这将导致这种设计方案不起作用。当我们看到session_cookie时,实际上csrf_cookie是缺失或无效的,此时我们会怀疑会话被固定并将用户登出。因此,简单的跨站点GET请求都将失败。

候选设计方案3Dropbox在强制登录模式下给CSRF cookie添加同站点属性。

候选设计方案3并不理想,因为即使是良性的GET请求,我们也经常检查会话cookie是否被绑定了加密CSRF令牌。


基于上述讨论,我们选择引入一个新的cookie__Host-samesite_cookie Cookie在强制模式下的具有同站点属性。我们将在所有支持同站点Cookie的浏览器上添加此类Cookie,我们会对相同浏览器上的每个相关请求中此类Cookie进行验证。

cookie的值来源于CSRF令牌。我们通过检查其存在以及其值的正确性来验证同站点cookie。我们检查该cookie的值为了防御会话固定(防止之前有攻击者设置了具有相同名称的cookie)。


最终设计:引入新的带有严格同站点属性的Cookie,其值从CSRF令牌派得出。

__Host-samesite_cookie处于强制模式下,这意味着它无法收到好的跨站GET请求(例如,从外部页面访问Dropbox公共链接)。 这是很好的,因为我们可以控制服务器端的执行。 如果请求是一个良性的GET请求,即便__Host-samesite_cookie不存在,我们仍然可以允许该请求通过。 但是,如果这是一个状态有变化的POST请求,且__Host-samesite_cookie不存在,那么我们可以将其视为一个CSRF错误。


我们可以控制服务器端的执行。良性的GET请求可以执行,因为我们可以忽略对非AJAX GET请求的同站点保护。

除此之外,我们将__Host-samesite_cookie定义为一个Host-prefix cookie__Host-prefix cookie的特性是:只能被发送到主机(发送cookie的)上。 www.dropbox.com的子域上的JavaScript无法设置此cookie。如果csrf_cookie__Host-samesite_cookie都有效,我们可以确信没有发生会话固化攻击。


实现

处理cookie认证是极具风险的,可能会产生许多可用性和安全性问题。在最糟糕的情况下,它可能会锁定许多用户(并强制他们手动重置Cookie),将用户登录到其他用户的帐户,或完全禁用我们的CSRF防御!

 

因此,我们决定分两个阶段实现同站点Cookie防御:首先在“仅警告”模式中实现,这时我们会记录所有错误,当没有任何意外的错误时,我们才会在“执行”模式下实现。此外,我们希望对我们要执行同站点属性检查的请求具有一定的灵活性。仅仅启用针对POST请求的同站点检查等同于我们当前的CSRF检查,但不一定能防止跨站原始信息泄漏也不一定对攻击进入点调查有帮助。

 

回顾一下,我们为支持__Host-samesite_cookie特点的浏览器添加了一种新的cookie __Host-samesite_cookie。该Cookie在强制模式下且具有SameSite属性,它的值来自csrf_cookie。对于以下请求,我们检查__Host-samesite_cookie的存在并验证:

1.   如果请求方法为“POST”,并且路由未列入用于跳过CSRF保护的白名单,当__Host-samesite_cookie无效时报告CSRF错误。(请注意,我们允许一些记录路由跳过CSRF保护。)

2.   如果请求是AJAX的并且请求方法是“GET”,则当__Host-samesite_cookie无效时报告潜在的跨站原始信息泄露错误。

3.    如果请求是非AJAX的并且请求方法是“GET”,则当__Host-samesite_cookie无效时将路由记录为潜在的入口点。


if not is_present_and_valid(cookies.get("__Host-samesite_cookie")):

  if request.method == "POST" and not skip_csrf_check(route): # Case 1

    report("CSRF error", route)

  elif request.type == "AJAX" and request.method == "GET": # Case 2

    report("Cross-origin error", route)

  elif request.type != "AJAX" and request.method == "GET": # Case 3

    log("entry_points_log", route)

  else:

    pass

在情况(1)中,我们发现了威胁最小的虚假警报,所以我们从警告模式切换到执行模式,为防止发生违规而返回HTTP 403错误。

情况(2)中,我们注意到一些AJAX GET请求,例如Saver所使用的是有意设计的跨站请求。我们在同站点检查中将这几个端点列入白名单。我们将这几个端点列入同站点检查的白名单。此外,我们注意到了AJAX GET请求所抓取的服务运行组件,__Host-samesite_cookie未被发送。我们向Chrome提交了一份错误报告。对于那些服务运行组件的路由,我们添加了一个额外的头文件来阻止跨站请求,而不是依靠cookie检查。 在此之后,我们相信可以在执行模式下推出上述方案。

对于情况(3),大多数网站“顶级”页面(如https://www.dropbox.comhttps://www.dropbox.com/help)都很少,大部分用户从这些根页面导航到其他页面(例如https://www.dropbox.com/team/admin/members),而非直接访问。 我们称这些“顶级”页面为入口点。强制用户只能通过从入口点导航访问非入口点可以减少网站遭受攻击的概率。

 

通过利用所有非AJAX GET路径的同一站点检查,我们找到了一些非入口点,如:

l  Dropbox团队管理员以管理其团队成员的帐户的登陆路径。

l  我们的帮助流程中的路径,用户在联系客服之前所回答的一系列问题

l  在执行操作之前,点击yes / no对话框上的“你确定吗?”的遗留路径

不过,我们注意到我们网站的非入口点比我们预期的要少得多。我们推测最新的Web应用程序可能只有少量非入口点,但我们很乐意听听您的想法。


结论

使用同站点Cookie能方便有效地防御各种跨源头请求攻击。由于并非所有浏览器都支持这一技术,我们建议最好将它作为一种深度防御的手段。我们希望将来其他浏览器能添加对这一技术的支持。


在现有CSRF防御基础上引入同站点Cookie技术应该能够在不影响可用性的前提下增加安全性。由于文章中所介绍的原因,我们建议添加一种新的Cookie,其在在强制执行模式下具有同站点属性,且在服务器端实际控制该属性的执行。该cookie应优选为__Host-prefix cookie,其值应优先从CSRF令牌导出。


Dropbox正在从支持同站点Cookie技术的新型浏览器所带来安全优势上受益。安全是我们公司的核心,我们很高兴为用户及其数据添加另一层保护。


原文https://blogs.dropbox.com/tech/2017/03/preventing-cross-site-attacks-using-same-site-cookies/
译者:jasonk龙莲于2017-4-13

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功