【问题标题】:CSRF protection by storing nonce in Session variable and form通过在 Session 变量和表单中存储 nonce 来保护 CSRF
【发布时间】:2011-01-16 01:19:09
【问题描述】:

为了防止 CSRF,您应该在表单的隐藏字段、cookie 或会话变量中放置一个 nonce。但是,如果用户在不同的选项卡中打开多个页面怎么办?在这种情况下,每个选项卡都会有一个带有唯一 nonce 的表单,但会话变量或 cookie 中只会存储一个 nonce。或者,如果您尝试将所有 nonce 存储在 cookie/session 变量中,您将如何识别哪个属于哪个表单?

【问题讨论】:

    标签: security csrf


    【解决方案1】:

    您所描述的不再是随机数(随机数 = 使用次数一次),它只是一个会话标识符。 nonce 的全部意义在于它仅对单个表单提交有效,因此提供了比仅会话 ID 更高的安全性来防止劫持,但代价是无法在站点上并行运行多个选项卡。

    Nonce 在很多情况下都是多余的。如果您使用它们,您应该只在对系统进行关键更改的表单上设置和要求它们,并告知用户他们不能期望并行使用多个这样的表单。未设置 nonce 的页面应注意不要从会话中清除任何先前存储的 nonce,以便用户仍然可以与 nonced 表单并行使用 non-nonced 页面。

    【讨论】:

      【解决方案2】:

      很久以前写过这篇文章。 我已经实现了一个我几乎可以肯定可以很好地保护的 csrf 阻止程序。 它确实适用于多个打开的窗口,但我仍在评估它提供的保护类型。它使用数据库方法,即存储而不是会话到表。 注意:在这种情况下,我使用 MD5 作为一种简单的反sqli 机制

      伪代码:

      表格:

      token = randomstring #to be used in form hidden input
      db->insert into csrf (token, user_id) values (md5(token),md5(cookie(user_id))
      

      -- 然后将令牌保存在数据库中,直到从下面的操作脚本中访问它:

      动作脚本:

      if md5(post(token)) belongs to md5(cookie(user_id)) 
          #discard the token
          db -> delete from csrf where token=md5(post(token)) and user_id=md5(cookie(user_id)) 
          do the rest of the stuff
      

      【讨论】:

      • 将用户 ID 添加到记录实际上并不会增加安全性,但它允许在断开连接时从数据库中删除用户未使用的令牌。
      【解决方案3】:

      有些人会为每个表单生成一个令牌,这是一种非常安全的方法。但是,这可能会破坏您的应用程序并激怒用户。为了防止所有 XSRF 针对您的站点,您只需要每个会话唯一的 1 个令牌变量,然后攻击者将无法伪造任何请求,除非他能找到这 1 个令牌。这种方法的一个小问题是,只要受害者正在访问攻击者控制的网站,攻击者就可以暴力破解这个令牌。但是,如果令牌非常大,例如 32 字节左右,那么暴力破解需要很多年,并且 http 会话应该在此之前很久就过期。

      【讨论】:

      • 攻击者不能只请求表单来获取有效令牌吗?看起来很简单。
      • @Chris Moschini 这不是 xsrf 的工作方式。你骑在别人的会话而不是你自己的会话上,这没有任何意义。
      • 谢谢。当服务器位于反向代理之后并且为每个请求更新 HTTP 会话时会怎样?
      【解决方案4】:

      您可以在每个表单中存储相同的随机数。最简单的方法是将 nonce 绑定到会话 ID,以便这些表单仅在该会话中有效。

      您需要让攻击者难以窃取会话 ID 并创建自己的随机数。因此,一种解决方法是使用 HMAC-SHA256(或类似方法)对会话 ID 进行哈希处理,使用您不向公众公开的密钥。

      (很明显,如果攻击者自己可以获取实际的会话 ID,他们就已经可以进行会话劫持了。所以这不是我要说的,而是攻击者制作脚本的能力(在受害者的计算机),它可以以某种方式获取会话 ID 并使用它来动态生成预先填充随机数的 URL。)


      ETA:上述方法本身是否足够取决于您期望典型会话持续多长时间。如果用户通常使用持续时间超过几个小时的长时间会话,则您需要使用更复杂的方法。

      一种方法是为每个表单创建一个新的 nonce,其中包含时间戳以及 hash(timestamp . sessionid)(其中 hash 是如上所述的 HMAC 的一些变体,以防止伪造,. 是字符串级联)。然后,您可以通过以下方式验证 nonce:

      1. 检查时间戳以确保 nonce 足够新鲜(这取决于您的政策,但通常需要几个小时)
      2. 然后,根据时间戳和会话 ID 计算哈希值,并与 nonce 进行比较,以验证 nonce 的真实性

      如果随机数检查失败,您需要显示一个新表单,其中预先填充了用户提交的内容(这样,如果他们花了一整天的时间来写帖子,他们就不会失去所有的辛勤工作) ,以及一个新鲜的随机数。然后用户可以直接重新提交成功。

      【讨论】:

      • 那么你不会每次都生成一个新的随机数吗?在整个会话期间,随机数将保持不变,并且对于多次提交。
      • @Marius:我会更新我的答案以回复您的评论。 :-)
      • -1 不,攻击者没有会话ID,浏览器有。这不是 HMAC 的工作。
      • 如果会话 id 在论坛中有什么关系,如果攻击者可以读取论坛,那么攻击者可以读取 javascript:document.cookie。我认为你不知道你在保护什么。
      • Nonce 代表 Number Used Once。如果你不止一次使用它,你就破坏了整个目的。
      猜你喜欢
      • 2017-07-27
      • 2018-04-19
      • 2016-09-27
      • 2021-09-07
      • 2016-08-10
      • 2018-11-03
      • 1970-01-01
      • 2011-02-16
      • 2012-09-28
      相关资源
      最近更新 更多