设置密码恢复尝试的限制

信息安全 php 密码管理 安全编码
2021-09-01 05:22:14

在一个忘记密码的环境中,我希望能够将输入电子邮件地址的尝试限制为 10 次。我的第一个想法是使用 cookie。

$attempts = 0;

if( isset( $_COOKIE['password_recovery_attempts'] ) ) 
  $attempts = $_COOKIE['password_recovery_attempts'];

if( $pass === false ){
  $val = $attempts + 1;
  setcookie( 'password_recovery_attempts', $val, time() + 86400 ); //86400 = 1 day
}

if( $attempts > 9 ){
  echo 'You have attempted to reset your password too many times';
  return false;
}

我对只使用 cookie 的担忧是,cookie 很容易被删除。这里有什么更好的做法?

3个回答

您说 cookie 是一个坏主意是对的,但这种方法本身是错误的。

这类硬限制的问题在于,它们使攻击者很容易为合法用户创建 DoS 条件,只需输入 10 个不正确的电子邮件地址。即使您对尝试进行延时,攻击者也可以在每次超过时间限制时简单地发送请求。

我实施它的方式是对每个 IP、每个帐户的请求进行时间限制,在第一次和第二次尝试后没有延迟,但将连续尝试的延迟增加到 45 秒的限制。另一个有用的措施是对来自 IP 地址的任何请求强制执行 45 秒延迟,该 IP 地址在过去 15 分钟内对任意数量的帐户进行了超过 10 次错误尝试,以防止扫描整个用户名列表的攻击针对一个已知的电子邮件地址。我也可能会考虑在一定次数的失败尝试后要求验证码,以防止自动攻击。

这提供了以下好处:

  • 只要攻击者使用不同的面向公众的 IP 地址,合法客户端将始终能够使用该功能(即无法达到 DoS 条件)。
  • 可以执行合理数量的失败尝试,而用户不会受到锁定机制的阻碍。
  • 有针对性的攻击和唾手可得的攻击都受到阻碍,对合法用户的负面影响最小。
  • 最坏的情况是攻击者与合法用户在同一网络上时会生成 DoS 条件。不完全关键或可能。

这将涉及将失败的尝试存储在服务器端的日志中,可能存储在数据库表或内存缓存中。

您永远不能信任客户端,而使用 cookie 就是这样——您依赖于客户端(可能是攻击者)向您发送准确的信息。为了使其正常工作,您需要存储此服务器端。

您可以将重置尝试计数与帐户数据一起存储,并在成功登录时将其重置为 0 - 适用于较小的站点。对于较大的站点,您希望将数据存储在单独的数据存储中 - memcached 或类似的(可能使用您用于服务器端会话数据的任何机制)。

您应该锁定帐户服务器端。设置 cookie 或暂时禁止 IP 都可以被客户端轻松规避。我建议采用一种机制来禁止用户在x尝试失败后重置。如果尝试超过 .php,您的 PHP 脚本应该检查您的数据库x