Security 什么是最好的分布式暴力对抗?

Security 什么是最好的分布式暴力对抗?,security,authentication,brute-force,Security,Authentication,Brute Force,首先,有一点背景:我正在为CodeIgniter实现一个auth+auth系统,这已经不是什么秘密了,到目前为止,我正在获胜(可以这么说)。但我遇到了一个非常重要的挑战(大多数auth库都没有遇到,但我坚持正确处理):如何智能地处理大规模、分布式、可变用户名的暴力攻击 我知道所有的惯用伎俩: 限制每个IP/主机的失败尝试次数#并拒绝违规者访问(例如Fail2Ban)-这不再有效 将上述内容与已知“坏”IP/主机的黑名单(如DenyHosts)结合起来,该黑名单依赖于落入#1的僵尸网络 IP/主机

首先,有一点背景:我正在为CodeIgniter实现一个auth+auth系统,这已经不是什么秘密了,到目前为止,我正在获胜(可以这么说)。但我遇到了一个非常重要的挑战(大多数auth库都没有遇到,但我坚持正确处理):如何智能地处理大规模、分布式、可变用户名的暴力攻击

我知道所有的惯用伎俩:

  • 限制每个IP/主机的失败尝试次数#并拒绝违规者访问(例如Fail2Ban)-这不再有效
  • 将上述内容与已知“坏”IP/主机的黑名单(如DenyHosts)结合起来,该黑名单依赖于落入#1的僵尸网络
  • IP/主机白名单与传统身份验证相结合(遗憾的是,对于动态IP用户和大多数网站上的高流失率来说毫无用处)
  • 在N分钟/小时内对失败的尝试设置一个站点范围的限制,并在此后的几分钟/小时内限制(暂停)所有登录尝试(DoS攻击您的问题将成为僵尸网络儿童游戏)
  • 强制数字签名(公钥证书)或RSA硬件令牌,适用于所有用户,无需登录/密码选项(毫无疑问,这是一个坚如磐石的解决方案,但仅适用于封闭的专用服务)
  • 强制的超强密码方案(例如>25个带有符号的无意义字符-同样,对于普通用户来说太不切实际了)
  • 最后,CAPTCHA(在大多数情况下都可以使用,但对用户来说很烦人,而且不利于安全)
  • 现在,这些只是理论上可行的想法。有很多垃圾想法会让网站大开方便之门(例如,琐碎的拒绝服务攻击)。我想要的是更好的。我所说的更好是指:

    • 它必须是安全的(+)以防DoS和暴力攻击,并且不引入任何新的漏洞,这些漏洞可能允许稍微狡猾的机器人继续在雷达下运行

    • 它必须是自动化的。如果它需要人工操作员来验证每个登录或监视可疑活动,那么它在现实场景中是行不通的

    • 它必须适用于主流网络使用(即高流失率、高容量和可由非程序员执行的开放注册)

    • 它不能妨碍用户体验,以至于临时用户会感到恼火或沮丧(并可能放弃网站)

    • 它不能涉及小猫,除非它们是真正安全的小猫

    (+)所谓“安全”,我的意思是至少和偏执狂用户保守密码的能力一样安全


    那么,让我们听听吧!你会怎么做?你知道我没有提到的最佳实践吗(哦,请说你知道)?我承认我确实有自己的想法(结合了第三和第四章的想法),但在让自己难堪之前,我会让真正的专家说出来;-)

    看起来你是在试图防御。你对此无能为力。我们使用的是PKI,没有密码登录。这是有帮助的,但是如果你的客户偶尔有机会使用工作站,这就不太适用了

  • 在输入他们的普通密码之前,是否需要一次性密码?这就很明显有人在猜到主密码之前就开始攻击了

  • 保持登录失败的全局计数/比率-这是攻击的指标-在攻击期间对登录失败更加严格,例如更快地禁止IP


  • 如果我正确理解暴力攻击的方式,那么就会不断尝试一个或多个用户名

    这里有两个我认为还没有看到的建议:

    • 我一直认为标准做法是在每个用户每次错误登录后都有一个短暂的延迟(一秒钟左右)。这阻止了暴力,但我不知道一秒钟的延迟能阻止字典攻击多久。(10000字字典==10000秒==大约3小时。嗯,不够好。)
    • 与其在站点范围内减速,不如使用用户名节流阀。每一次错误的尝试都会使油门变得越来越猛(我想这会达到一个极限,这样真正的用户仍然可以登录)
    编辑: 回应关于用户名限制的评论:这是一个特定于用户名的限制,不考虑攻击的来源

    如果用户名被限制,那么即使是协调的用户名攻击(多IP,每个IP一次猜测,相同的用户名)也会被捕获。即使攻击者可以在超时期间尝试其他用户/密码,单个用户名也会受到限制的保护

    从攻击者的角度来看,在超时期间,您可以第一次猜测100个密码,并快速发现每个帐户一个错误的密码。在同一时间段内,您可能只能进行50秒的猜测

    从用户帐户的角度来看,破解密码仍然需要相同的平均猜测次数,即使猜测来自多个来源

    对于攻击者来说,最好的情况是,破解100个帐户的努力与破解1个帐户的努力是一样的,但是由于您没有在站点范围内进行节流,因此可以非常快地加大节流

    额外改进:

    • 检测猜测多个帐户的IP-408请求超时
    • 检测猜测同一帐户的IP-408在大量(比如100次)猜测后请求超时
    UI想法(可能不适用于此上下文),这也可能完善上述内容:

    • 如果您可以控制密码设置,则显示给用户会鼓励他们选择更好的密码
    • 如果您控制了登录页面,在进行少量(比如10次)的猜测之后
      CREATE TABLE failed_logins(
          id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
          username VARCHAR(16) NOT NULL,
          ip_address INT(11) UNSIGNED NOT NULL,
          attempted DATETIME NOT NULL
      ) engine=InnoDB charset=UTF8;
      
      10 failed attempts = 1 second
      20 failed attempts = 2 seconds
      30 failed attempts = reCaptcha
      
      SELECT COUNT(1) AS failed FROM failed_logins WHERE attempted > DATE_SUB(NOW(), INTERVAL 15 minute);
      
      // array of throttling
      $throttle = array(10 => 1, 20 => 2, 30 => 'recaptcha');
      
      // assume query result of $sql is stored in $row
      $sql = 'SELECT MAX(attempted) AS attempted FROM failed_logins';
      $latest_attempt = (int) date('U', strtotime($row['attempted']));
      // get the number of failed attempts
      $sql = 'SELECT COUNT(1) AS failed FROM failed_logins WHERE attempted > DATE_SUB(NOW(), INTERVAL 15 minute)';
      // assume the number of failed attempts was stored in $failed_attempts
      krsort($throttle);
      foreach ($throttle as $attempts => $delay) {
          if ($failed_attempts > $attempts) {
              // we need to throttle based on delay
              if (is_numeric($delay)) {
                  $remaining_delay = time() - $latest_attempt - $delay;
                  // output remaining delay
                  echo 'You must wait ' . $remaining_delay . ' seconds before your next login attempt';
              } else {
                  // code to display recaptcha on login form goes here
              }
              break;
          }
      }