CSRF cookie 需要是 HttpOnly 吗?

信息安全 http 饼干 csrf django
2021-08-15 05:48:38

我们最近收到了一份安全报告,其中包含:

没有设置 HttpOnly 标志的 Cookie

漏洞,我们显然存在于我们的一个内部应用程序中。

应用的修复就像将 Django 的CSRF_COOKIE_HTTPONLY配置参数设置为True.

但是,这让我感到困惑。Django 文档说:

将 CSRF cookie 指定为 HttpOnly 并不能提供任何实际保护,因为 CSRF 只是为了防止跨域攻击。如果攻击者可以通过 JavaScript 读取 cookie,就浏览器所知,他们已经在同一个域中,所以他们可以做任何他们喜欢的事情。(XSS 是一个比 CSRF 大得多的漏洞。)

尽管该设置几乎没有什么实际好处,但安全审计员有时会要求这样做。

这是否意味着这里没有实际的漏洞,我们只需要遵守安全审计规则吗?

4个回答

正如joe 所说,这并没有真正的安全优势。这是纯粹的安全剧院。我想从文档中强调这一点:

如果您启用此功能并需要通过 AJAX 请求发送 CSRF 令牌的值,则您的 JavaScript 必须从页面上隐藏的 CSRF 令牌表单输入中提取值,而不是从 cookie 中提取值。

HttpOnly 标志的目的是使 cookie 的值无法从 JavaScript 中获取,这样如果存在 XSS 漏洞就不会被窃取。但是 CSRF 令牌必须以某种方式可用,以便可以重复提交 - 毕竟,这就是它的全部意义所在。所以 Django 通过将值包含在隐藏的表单字段中来解决这个问题。这否定了 HttpOnly 的全部好处,因为攻击者只能读取表单字段的值而不是 cookie。

那是对的。这是一个误报,不幸的是,向您提供此发现的人不明白他们在做什么。了解 mitm 和 csrf 攻击风险的人永远不会向您提供此信息。

我认为这里的主要混淆点是 Django 文档专门讨论了 cookie 的CSRF用例。为了理解为什么该httpOnly标志在阻止 CSRF 方面没有任何价值,您需要了解 CSRF 和 cookie 的工作原理。

CSRF 是指第 3 方触发您的用户浏览器向您的服务器发出请求,并且他们的浏览器按预期自动发送您服务器的 cookie 以及请求。您不希望您的服务器将此请求解释为实际来自您的用户,因此您使用CSRF 缓解技术。CSRF 缓解的全部意义在于能够检测到请求何时不是来自您自己的域(即来自与您的应用程序交互的用户)

简而言之,cookie 的工作原理:每当用户的浏览器向您的域/服务器发送请求时,它会自动发送与您的域相关联的所有 cookie,而不管httpOnly标志如何。因此,Cookie 允许您的客户端或您的服务器将信息附加到用户的浏览器,这些信息将与任何后续请求一起自动返回到您的服务器。httpOnly无法从 javascript 访问带有标志的 Cookie 。它们可能不应该被视为存储信息的安全场所,但它们确实提供了宣传的功能。

回到使用 cookie 实现的 CSRF——在这种情况下httpOnly标志毫无意义——CSRF 的关键在于它们不需要读取用户的 cookie,它们只需要用户的浏览器将相关的 cookie 连同网络请求,他们强迫它发送。通常,该httpOnly标志确实提供了价值,因为它阻止客户端访问这些 cookie,如果您的服务器返回任何 cookie,您可能应该将它们设置为httpOnly. 如果你为 CSRF 使用 cookie,那么你不应该那样做,你应该花时间重新考虑,而不是让它成为一个httpOnlycookie。所以,总的来说,这似乎是一个很好的经验法则——你的服务器不应该发送任何非httpOnly cookie,除非它是专门供客户端 javascript 访问的。

使用双重提交防止 CSRF 的唯一方法是在 cookie 中发送 nonce。如果您在 HTTP 响应正文中发送它,在某些情况下,它可能会被发送跨域请求的脚本解析出来(如果您允许该页面使用 CORS),这会破坏防止 CSRF 的整个目的。这个想法是域 X 上的脚本无法获取域 Y 上 cookie 的值,这是 Web 安全性的主要支柱之一。

使用 HTTPOnly cookie,您将无法使用最常用的方法来防止 CSRF - 即通过 cookie 双重提交 nonce 和能够读取 cookie 的页面上的脚本。以下是该技术的工作原理:

1) 为会话生成一个存储在服务器上的nonce值。它可能是会话 ID 本身,也可能是存储在与会话关联的数据中的东西。

2) 通过不带HTTPOnly的 cookie 标头将其发送到客户端,让一些 Javascript 抓取并存储它(例如短期或在 sessionStorage 中)

3) 与您希望保护免受 CSRF 影响的每个请求一起提交。请求将在 cookie 中包含 sessionId,在请求正文或 URL 查询字符串中也有这个 nonce(例如,对于 GET 请求)。如果您担心日志中的 nonce 或其他内容,您可以使用Web Crypto 使用此 nonce 使用 HMAC 对请求有效负载进行签名

4)服务器会查找会话数据,检查nonce是否不匹配,抛出错误并生成另一个nonce并发送到cookie中。确保仅在 cookie 中发送随机数!

不幸的是,许多“安全审计”工具开始标记未标记 httpOnly 的 cookie,并建议添加此标记。可悲的是,这面旗帜比无用更糟糕:它是安全剧院。

我说的只是 httpOnly 标志。这比无用更糟糕,因为它让你认为你躲过了某种子弹,而实际上同样的攻击仍然可能发生:攻击者需要编写一个脚本来将 cookie 发送到他们的服务器,所以他们不妨该脚本在您的授权会话的上下文中执行实际请求,就像他们拥有您的 cookie 时那样。他们会提前写好剧本。没有真正的攻击者会在凌晨 3 点坐在那里发出请求,因为他们的受害者最终激活了一个向他们发送 cookie 的脚本。更有可能的是,该脚本已经预先编程以执行它需要执行的操作。如果不存在 httpOnly cookie,人们会更关心清理他们的 Javascript 输出以防止 XSS,