php - 在 session 中存储 CSRF key ?

标签 php session encryption csrf

我正在尝试学习如何使用 CSRF token 来保护我的表单,根据我所读到的内容,我认为我所做的事情是安全的,但我对此了解不够,无法真正验证该声明。

到目前为止,我正在做以下步骤:

  1. 使用openssl_random_pseudo_bytes();生成 key ,然后将该 key 存储在 session 中。该 key 是在首次创建 session 时生成的。

  2. 在每个页面上使用 key 加密 session ID 以生成 CSRF token ,方法是:

    $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($key), session_id(), MCRYPT_MODE_CBC, md5(md5($key))));
    
  3. 将该 CSRF token 放入表单的隐藏输入中。

  4. 在页面加载时检查帖子,如果是帖子,则解密 CSRF token 并使用 Session_id 进行比较

    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($key), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5($key))), "\0");
    
  5. 如果解密的 token 与 session ID 匹配,则继续填写表单,否则,注销用户并重定向到主页。

到目前为止我遇到的问题如下:

  1. 攻击者是否有可能劫持 session 并获取 key ?如果是这样,考虑到他们不知道我用所述 key 加密的内容,这是否会损害检查的完整性?

  2. 我知道到目前为止没有任何东西容易受到 XSS 攻击(据我所知),那么攻击者是否有可能从合法用户那里获取 CSRF token ?

  3. 这种设置方式,每个 session 仅生成一次 CSRF token ,这似乎不太安全,即使 session 和 token 在几个小时后超时。是否应该在每次页面加载时生成 token ?如果是这样,这不会让使用多个选项卡的用户感到困惑吗?

感谢任何帮助,我仍在努力学习所有这些,并且安全性比我最初想象的要复杂得多。

最佳答案

  1. 如果您的应用程序上存在 XSS,攻击者就可以窃取 session 。但窃取 key 看起来更困难,因为它永远不会暴露给前端。

  2. 可能还有其他漏洞可能导致 token 劫持,例如不安全的通信。代币总是有可能被盗。

  3. 作为一项改进,可以为每个表单再次生成 CSRF token 。在这种情况下,应为每个用户 session 存储生成的有效 CSRF token 的列表。因此,在某一特定时刻,用户可能有多个有效的 CSRF token 。这将允许用户在多个选项卡上工作。

您可能想阅读OWASP Session Management Recommendations 。虽然有点长,但是很有帮助。

我认为,与它的好处相比,为每个页面创建一个新的 CSRF token 有点过于“安全”。事实上OWASP CSRF Prevention Cheat Sheet描述了每个 session 使用单个 token 的预防措施。

此外,使用单向散列(如 sha-512)创建 token 比加密 session ID 更安全。

关于php - 在 session 中存储 CSRF key ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22459499/

相关文章:

php mysql AND 运算符

php - 如何使用Jquery ajax设置$_SESSION?

python - 函数 pgp_sym_encrypt(numeric, unknown) 不存在

language-agnostic - 数字的 Rot13

php - 使用 mysql 在矩形或圆中查找点

php - Symfony2 FOSUserBundle 无法更新 Doctrine 数据库模式或清除缓存

javascript - 如何执行删除 MySQL 数据库条目的确认弹出窗口?

javascript - Nodejs session 未定义

jquery - 将字体大小保存到 session 中

java - Java 中的加密技术保留输入文本的格式