【问题标题】:Why is aspnet preventing browser page caching when a csrf token is present?为什么当存在 csrf 令牌时,aspnet 会阻止浏览器页面缓存?
【发布时间】:2021-10-18 15:42:19
【问题描述】:

正如 here 所记录的,使用 asp.net 生成 csrf 令牌也会阻止响应被浏览器缓存。

为此请求生成一个 AntiforgeryTokenSet 并将 cookie 令牌存储在响应中。此操作还将“Cache-control”和“Pragma”标头设置为“no-cache”,将“X-Frame-Options”标头设置为“SAMEORIGIN”。

我最初认为做出此决定是为了防止用户使用浏览器的“返回”按钮提交“陈旧的”请求令牌。后来我注意到这可能不是原因,因为:

  • asp.net 为整个会话保留相同的 cookie 令牌。
  • asp.net 允许多次提交相同的请求令牌,只要 cookie 令牌不变。

那么,以我目前的理解,使用浏览器的后退按钮并提交一个缓存的html页面应该没有问题吧?

当浏览器页面包含 csrf 令牌时,禁用浏览器页面缓存的理由是​​什么?这是安全最佳做法吗?

编辑

正如@serpent5 正确指出的那样,标头Cache-Control: no-store 确保公共缓存不会缓存响应并将其提供给不同的用户。澄清一下,我更想知道启用浏览器缓存 (Cache-Control: private) 是否会对安全性产生负面影响。

【问题讨论】:

    标签: asp.net-core security csrf


    【解决方案1】:

    您已经很好地描述了ASP.NET 中的防伪保护设置。
    另外,我在下面附上了官方文档的部分内容。

    要记住的主要事情是,会生成一组令牌,这些令牌会进入会话 cookie 和隐藏的表单标签,并且只有存在该确切组合才能通过安全检查。
    当会话到期时,会生成新的令牌。

    现在不允许私有缓存的原因与到期时间有关。

    如果网页的缓存持续时间超过反 XSRF 会话的到期时间,用户最终会得到来自缓存的先前/旧令牌,因为该令牌正在被重用。 提交该网页时,服务器端安全检查将失败,以防启动新会话(直到页面缓存失效)。

    由于反 XSRF cookie 是会话 cookie,它们会在关闭 Web 浏览器时被删除。在后续请求中,将启动新会话并生成新令牌。相应的仍然有效的缓存网页的存在将立即导致上述安全检查失败的情况。


    来自XSRF/CSRF Prevention in ASP.NET MVC and Web Pages文档的一些引用

    ASP.NET Web 堆栈运行时使用同步器令牌的变体 防御 XSRF 攻击的模式。的一般形式 同步器令牌模式是提交两个反 XSRF 令牌 使用每个 HTTP POST 到服务器(除了身份验证 token):一个令牌作为 cookie,另一个作为表单值

    在初始生成令牌后的每会话令牌实现中, 该值存储在会话中,并用于每个后续 请求直到会话过期

    提交令牌后,服务器将允许请求 仅当两个令牌都通过比较检查时才继续

    如果在步骤 (1) 中生成了一个新的反 XSRF 令牌,则 一个新的会话 令牌 将被创建以包含它并将添加到出站 HTTP cookie 集合。步骤 (2) 中的字段令牌将被包装 在 <input type="hidden" /> 元素中

    【讨论】:

    • 非常感谢您的详细解答!我想我明白为什么如果 Web 浏览器缓存寿命超过会话,检查会失败。但是,我仍然不确定Cache-Control: private 何时会发生这种情况。我注意到浏览器似乎没有重用 private 响应,除非在向后/向前导航时(我在这里可能错了吗?)。 RFC 7234 确实似乎允许重用这个响应。是 asp.net 只是通过严格遵循 RFC 7234 更加谨慎,还是我错过了会导致 Web 浏览器出现问题的真实场景?
    • 只要没有新会话开始,重复使用令牌就可以了。在活动会话中向后导航时,令牌不会更改,因为它仍然是同一个会话。当今天请求的网页缓存持续时间为 2 天时,隐藏的表单字段令牌将在明天被重用,届时将开始一个具有新令牌预期的新会话。
    • 不知道你的意思 “浏览器似乎没有重复使用私人响应”;当缓存标头已正确设置(具有过期或最大年龄)时,将考虑缓存数据。
    • 我的意思是单独使用Cache-Control: private(没有 max-age/expires),浏览器似乎永远不会显示缓存的响应,除非使用浏览器历史记录(我找不到来源来确认这)。 aspnet 添加的Cache-Control: no-store 给我们的一些用户带来了一些问题,因为当他们返回浏览器的历史记录时表单字段值的状态会丢失(这会迫使浏览器重新加载页面)。所以我们正在考虑改用Cache-Control: private(+ 清除所有 max-age/expires 标头),但我们不确定这是否会引入错误/安全漏洞。
    • 我已接受您的回答,因为它回答了原始问题。再次感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 2015-08-20
    • 2013-11-05
    • 1970-01-01
    • 2014-05-26
    • 2012-06-19
    • 2013-01-24
    相关资源
    最近更新 更多