首页 文章

通过在会话变量和表单中存储nonce来保护CSRF

提问于
浏览
10

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

4 回答

  • 6

    您可以在每个表单中存储相同的随机数 . 最简单的方法是将nonce与会话ID绑定,以便这些表单仅在该会话中起作用 .

    您将希望攻击者难以snarf会话ID并创建自己的nonce . 因此,一种方法是使用HMAC-SHA256(或类似方法)来散列会话ID,使用您不向公众公开的密钥 .

    (显然,如果攻击者本身可以获得实际的会话ID,他们就已经可以进行会话劫持 . 所以这不是我所说的,而是攻击者制作脚本(在受害者的计算机上运行)的能力可以以某种方式获取会话ID并使用它来动态生成带有nonce预填充的URL . )


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

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

    • 检查时间戳以确保nonce足够新鲜(这取决于您的策略,但通常是几个小时)

    • 然后,根据时间戳和会话ID计算哈希值,并与nonce进行比较,以验证nonce是否是真实的

    如果nonce检查失败,你将需要显示一个新的表单,预先填充用户的提交(如果他们花了一整天写他们的帖子,他们将不会失去他们所有的辛勤工作),以及作为一个新鲜的nonce . 然后用户可以成功立即重新提交 .

  • 3

    你所描述的不再是一个nonce(nonce = number used once ),它只是一个会话标识符 . nonce的重点在于它仅对单个表单提交有效,因此提供更强的安全性来防止劫持而不仅仅是会话ID,但代价是无法在站点上并行运行多个选项卡 .

    Nonces对于许多目的来说都是矫枉过正的 . 如果您使用它们,则只应在对系统进行重要更改的表单上设置和要求它们,并教育用户不要期望并行使用多个此类表单 . 不设置随机数的页面应注意不要清除会话中任何先前存储的随机数,以便用户仍可以使用非随机页面与非表单形式并行使用 .

  • 2

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

  • 0

    很久以前写这篇文章了 . 我已经实现了一个csrf阻止程序,我几乎可以肯定它可以很好地保护 . 它可以在多个打开的窗口中运行,但我仍在评估它提供的保护类型 . 它使用DB方法,即将表而不是会话存储到表中 . 注意:在这种情况下,我使用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
    

相关问题