将某人登录到网站的最安全方法是什么?

What is the most secure method of logging someone into a website?

我正在尝试确定在验证登录正确后让某人继续登录我的网站的最佳方法。

我试着查看 "Keep Me Logged In" - the best approach,其中最赞的答案说我应该生成一个令牌,然后将此令牌存储在数据库中!这肯定是完全不安全的,因为只需要破解数据库和编辑 cookie 就可以进入别人的帐户吗?

有人可以向我提供最新的安全方法吗?谢谢

将生成的令牌以明文形式存储在数据库中显然是一种风险,但通常被认为是可以接受的。一种缓解技术是要求用户在执行敏感操作之前重新进行身份验证。例如,亚马逊似乎要求我在修改帐户详细信息之前输入密码,除非我最近输入过密码。

我们最近 post 写了一篇关于 secure authentication with long-term persistence (a.k.a "Remember Me"), but the largest difference between this blog post and ircmaxell's answer to "Keep Me Logged In" - the best approach is a separation of the lookup (which is not constant-time) 和验证(恒定时间)的博客。

在我们的博客 post 中概述的策略中,您不是在数据库中存储令牌,而是存储令牌的 SHA-256 哈希值。如果攻击者泄露了这些值,他必须破解强随机令牌的 SHA-256 哈希。他们最好只启动一个反向 shell,让他们以任何用户身份进行身份验证(或者继续使用本地内核漏洞利用来接管整个机器)。

登录(简单和基本)

  • 使用 bcrypt。 具体 password_verify()不要生成自己的盐。

    如果您想更进一步,请考虑这个 bcrypt + AES 库来加密密码哈希值(如果您的数据库和网络服务器位于不同的硬件上,这将非常有用,因为破坏数据库不会给他们加密密钥)。

  • 速率限制失败尝试。例如:每个 IP 或用户名失败 5 次后,需要验证码。

长期坚持("Remember Me")

登录时:

  1. 生成一个安全的随机令牌。
  2. 生成一个安全的随机标识符。
  3. 将标识符和令牌存储在 rememberme cookie 中。
  4. 在数据库中存储令牌的 SHA256 哈希值。
  5. 当用户登陆页面时,如果他们有 rememberme cookie,获取标识符并进行数据库搜索。
  6. 如果此标识符有身份验证令牌,请获取 SHA256 哈希值。
  7. 使用 hash_equals().
  8. 将 cookie 提供的令牌的哈希值与数据库中的 SHA256 哈希值进行比较
  9. 如果成功,将会话变量设置为该用户的 ID。生成一个新的令牌。如果失败,则从数据库中删除该条目。

此策略的优势

  • 如果成功的SQL注入攻击导致令牌泄露,攻击者所拥有的只是各种令牌的SHA256哈希值。这对破坏帐户没有帮助。
  • 数据库搜索不是 constant-time。这就是标识符与令牌分开的原因。
  • 顺序标识符会泄露应用程序的 activity 级别,许多企业希望对其保密。随机标识符混淆了这个细节。

缺点

  • (如果有任何发现,未来的 Whosebug 作者应该随时填充此列表。)