什么是最好的分布式蛮力对策?

时间:2009-01-26 09:37:29

标签: security authentication brute-force

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

我知道所有常用的技巧:

  1. 限制每个IP /主机失败的尝试次数并拒绝违规者访问(例如Fail2Ban) - 不再有效since botnets have grown smarter
  2. 将上述内容与已知“坏”IP /主机的黑名单相结合(例如DenyHosts) - 它依赖僵尸网络为#1,which they increasingly don't
  3. IP /主机白名单与传统的身份验证相结合(对于动态IP用户而言,在大多数网站上流失率很高)。
  4. 在N分钟/小时内对失败的尝试次数设置全站限制,并在此之后限制(暂停)所有登录尝试,持续数分钟/小时(问题是DoS)攻击你成为僵尸网络孩子的游戏)
  5. 强制数字签名(公钥证书)或RSA硬件令牌,适用于没有登录/密码选项的所有用户(毫无疑问是坚如磐石的解决方案,但仅适用于封闭的专用服务)
  6. 强制超强密码方案(例如> 25个含有符号的无意义字符 - 再次,对于临时用户来说太不切实际了)
  7. 最后, CAPTCHAs (在大多数情况下都可以使用,但对用户而言很烦人,virtually uselessdetermined, resourceful attacker感到烦恼)
  8. 现在,这些只是理论上可行的想法。有足够的垃圾思想可以打开网站(比如琐碎的DoS攻击)。我想要的是更好的东西。更好的是,我的意思是:

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

    • 必须自动化。如果需要人工操作员验证每次登录或监控可疑活动,则无法在真实场景中使用

    • 主流网络使用必须是可行的(即非流程,高流量,非开放注册,可以由非程序员执行)

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

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

    (+)通过'secure',我的意思是至少和偏执的用户保密密码一样安全

    所以 - 让我们听听吧! 你会怎么做?你知道我没有提到过的最佳实践(哦,请你说)吗?我承认我确实有自己的想法(结合3和4的想法),但我会让真正的专家在让自己尴尬之前发言; - )

15 个答案:

答案 0 :(得分:66)

答案 1 :(得分:17)

一些简单的步骤:

将某些常见用户名列入黑名单,并将其用作蜜罐。管理员,访客等...不要让任何人创建具有这些名称的帐户,因此如果有人确实尝试将其记录下来,您就知道有人做了他们不应该做的事情。

确保网站上拥有真正威力的任何人都拥有安全密码。要求管理员/主持人拥有更长的密码,其中包含字母,数字和符号。拒绝来自普通用户的简单密码并附上说明。

您可以做的最简单的事情之一就是告诉别人有人试图登录他们的帐户,并给他们一个链接报告事件,如果不是他们。 当他们登录时发出一条简单的消息,例如“有人试图在星期三凌晨4:20登录您的帐户,等等等等。如果不是您,请点击此处。”它可以让你保留一些攻击统计数据。如果您发现欺诈性访问突然增加,您可以加强监控和安全措施。

答案 2 :(得分:11)

如果我理解了暴力攻击的MO,那么就会连续尝试一个或多个用户名。

有两条建议,我认为我还没有在这里看到过:

  • 我一直认为标准做法是在每次错误登录后为每个用户提供短暂的延迟(大约一秒钟)。这可以阻止蛮力,但我不知道一秒钟的延迟会在多长时间内阻止字典攻击。 (10000字的字典== 10,000秒==约3小时。嗯。不够好。)
  • 而不是网站范围内的减速,为什么不是用户名限制。每次错误的尝试都会越来越苛刻(达到极限,我想真正的用户仍然可以登录)

修改: 回应有关用户名限制的评论:这是一个特定于用户名的限制,而不考虑攻击的来源。

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

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

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

对于攻击者来说,最好的情况是打破100个帐户和1个帐户一样,但由于你没有在网站范围内进行限制,你可以很快地提高速度。

额外改进:

  • 检测猜测多个帐户的IP - 408请求超时
  • 检测猜测同一帐户的IP - 在大量猜测(例如100次)之后请求超时。

UI想法(可能不适用于此上下文),这也可能会改进上述内容:

  • 如果您控制密码设置,则向用户显示how strong their password is会鼓励他们选择更好的密码设置。
  • 如果您控制登录页面,在对一个用户名进行少量(例如10次)猜测后,请提供CAPTCHA。

答案 3 :(得分:9)

认证有三个因素:

  1. 用户知道某些内容(即密码)
  2. 用户拥有某些内容(即密钥卡)
  3. 用户 某事(即视网膜扫描)
  4. 通常,网站只执行政策#1。甚至大多数银行只执行政策1.他们依赖于“了解其他”方法进行双因素身份验证。 (IE:用户知道他们的密码和他们母亲的婚前姓名。)如果你有能力,添加第二个身份验证因素的方法并不太难。

    如果你可以生成大约256个字符的随机性,你可以在16×16表中构造它,然后让用户给你一个例如单元格A-14表中的值。当用户注册或更改密码时,请向他们提供表格并告诉他们将其打印并保存。

    这种方法的难点在于,当用户忘记密码时,您不能只提供标准“回答这个问题并输入新密码”,因为这也很容易受到蛮力的攻击。此外,您无法重置它并通过电子邮件发送新的电子邮件,因为他们的电子邮件也可能会受到影响。 (请参阅:Makeuseof.com及其被盗域名。)

    另一个想法(涉及小猫)是BOA所谓的SiteKey(我相信他们注册了这个名字)。简而言之,您可以让用户在注册时上传图像,当他们尝试登录时,要求他们从8或15个(或更多)随机图像中选择图像。因此,如果用户上传他们的小猫的照片,理论上只有他们确切地知道他们的所有其他小猫(或花或其他)的图片。这种方法唯一真正的可用性是中间人攻击。

    另一个想法(尽管没有小猫),是跟踪用户访问系统的IP,并要求他们在从用户登录时执行其他身份验证(验证码,选择小猫,从此表中选择密钥)他们之前没有的地址。此外,与GMail类似,允许用户查看他们最近登录的位置。

    编辑,新主意:

    验证登录尝试的另一种方法是检查用户是否来自您的登录页面。您无法检查引荐,因为它们很容易被伪造。您需要的是在用户查看登录页面时在_SESSION var中设置密钥,然后在提交登录信息时检查以确保该密钥存在。如果bot没有从登录页面提交,它将无法登录。您还可以通过在流程中使用javascript来实现此目的,方法是使用它来设置cookie,或者在加载后向表单添加一些信息。或者,您可以将表单拆分为两个不同的提交(即,用户输入他们的用户名,提交,然后在新页面输入他们的密码并再次提交。)

    在这种情况下,关键是最重要的方面。生成它们的常用方法是用户数据,IP和提交时间的某种组合。

答案 4 :(得分:6)

我不得不问你是否对这个问题进行了成本效益分析;听起来你正试图保护自己免受攻击者的攻击,他们有足够的网络存在来猜测一些密码,每个IP可能发送3-5个请求(因为你已经解除了IP限制)。这种攻击会花费多少(大致)?它比您要保护的帐户的价值更贵吗?有多少庞大的僵尸网络想要你拥有的东西?

答案可能是否定的 - 但如果是,我希望你能得到某种安全专业人士的帮助;编程技能(和StackOverflow得分)与安全技术诀窍没有很强的关系。

答案 5 :(得分:6)

我之前在How can I throttle user login attempts in PHP回答了一个非常类似的问题。我将重申这里提出的解决方案,因为我相信你们中的许多人会发现看到一些实际的代码是有用的和有用的。请记住,使用CAPTCHA可能不是最佳解决方案,因为现在CAPTCHA破坏者使用的算法越来越准确:

您不能通过将限制链接到单个IP或用户名来简单地阻止DoS攻击。好吧,你甚至无法阻止使用这种方法的快速登录尝试。

为什么? 因为攻击可以跨越多个IP和用户帐户,以便绕过限制尝试。

我已经看到在其他地方发布过,理想情况下,您应该跟踪网站上所有失败的登录尝试并将它们与时间戳相关联,或许:

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;

根据给定时间内整体失败登录次数确定某些延迟。您应该根据从failed_logins表中提取的统计数据,因为它将根据用户数量随时更改以及有多少人可以调用(和键入)他们的密码。< / p>


10 failed attempts = 1 second
20 failed attempts = 2 seconds
30 failed attempts = reCaptcha

在每次失败的登录尝试时查询表,以查找给定时间段(例如15分钟)的登录失败次数:


SELECT COUNT(1) AS failed FROM failed_logins WHERE attempted > DATE_SUB(NOW(), INTERVAL 15 minute);

如果超过给定时间段的尝试次数超过限制,则强制限制或强制所有用户使用验证码(即reCaptcha),直到给定时间段内失败尝试次数小于阈值为止。

// 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;
    }
}

在特定阈值下使用reCaptcha可确保来自多个前端的攻击最小化,并且正常站点用户不会遇到合法失败登录尝试的重大延迟。我无法保护预防,因为已经扩展了CAPTCHA可以被破坏。还有其他解决方案,可能是“命名这种动物”的变体,它可以很好地替代它。

答案 6 :(得分:5)

将Jens的方案概括为伪状态转换图/规则库:

  1. 用户+密码 - &gt;条目
  2. 用户+!密码 - &gt;拒绝
  3. user + known_IP(user) - &gt;前门,// never throttle
  4. user + unknown_IP(user) - &gt; catflap
  5. (#denied&gt; n)通过catflaps(网站) - &gt;节流catflaps(网站)// slow the bots
  6. catflap + throttle +密码+验证码 - &gt;条目// humans still welcome
  7. catflap + throttle +密码+!captcha - &gt;否认// a correct guess from a bot
  8. 观察:

    • 永远不要踩下前门。 Elbonian州警察把你的电脑放在你的房子里,但却无法审问你。蛮力是您计算机的可行方法。
    • 如果您提供“忘记密码?”链接,然后您的电子邮件帐户成为攻击面的一部分。

    这些观察结果涵盖了对你试图反击的攻击的不同类型的攻击。<​​/ p>

答案 7 :(得分:4)

看起来你正试图防御slow distributed brute force。你可以做的不是那么多。我们使用的是PKI,没有密码登录。它会有所帮助,但如果您的客户偶尔偶然使用工作站,则这不太适用。

答案 8 :(得分:3)

免责声明:我为一家双因素公司工作,但我不是来插电的。这里有一些观察。

使用XSS和浏览器漏洞可以窃取Cookie。用户通常会更改浏览器或清除其Cookie。

源IP地址同时是动态变量和可欺骗的。

验证码很有用,但不会对特定人员进行身份验证。

多种方法可以成功组合,但良好的口味肯定是有序的。

密码复杂性很好,任何基于密码的关键都取决于具有足够熵的密码。恕我直言,在安全的物理位置写下的强密码比内存中的弱密码更好。人们知道如何评估纸质文档的安全性比他们知道如何在用作三个不同网站的密码时用他们的狗的名字来计算有效熵更好。考虑让用户能够打印出一次性使用密码的大页或小页。

诸如“你的高中吉祥物是什么”之类的安全问题大多是另一种糟糕的“你知道的东西”形式,其中大多数都很容易被猜到或者在公共领域是彻头彻尾的。

正如您所指出的,限制失败登录尝试是在防止暴力攻击和轻松执行帐户之间进行权衡。激进的锁定策略可能反映出对密码熵缺乏信心。

我个人认为无论如何都不会在网站上强制执行密码过期。攻击者获取您的密码一次,然后他就可以更改密码并尽可能轻松地遵守该策略。也许一个好处是,如果攻击者更改了帐户密码,用户可能会更快注意到。如果用户在攻击者获得访问权之前以某种方式得到通知,那就更好了。像“上次登录后N次尝试失败”这样的消息在这方面很有用。

最好的安全性来自第二个身份验证因素,相对于第一个因素是带外的。就像你说的那样,“你拥有的东西”中的硬件令牌很棒,但很多(并非所有)都有与其分发相关的真正的管理开销。我不知道任何生物识别“你是什么”的解决方案对网站有益。一些双因素解决方案适用于openid提供程序,其中一些具有PHP / Perl / Python SDK。

答案 9 :(得分:1)

  1. 在输入正常密码之前需要一次性密码怎么办?这会让很明显有人在他们有很多猜测主密码的机会之前进行攻击吗?

  2. 保持全局计数/登录失败率 - 这是攻击的指标 - 在攻击过程中对登录失败更严格,例如禁止IP更快。

答案 10 :(得分:1)

我的最高建议是确保您让用户了解对其帐户的不良登录尝试 - 如果向用户提供证据证明某人实际上正在尝试进入他们的帐户,则用户可能会更加认真地使用他们的密码。

我实际上抓住了一个入侵我兄弟的myspace帐户的人,因为他们曾试图进入我为他设置的gmail帐户,并使用了“通过电子邮件重置我的密码”功能...进入我的收件箱。

答案 11 :(得分:0)

我不相信有一个完美的答案,但如果感觉到攻击,我会倾向于试图混淆机器人。

脱离我的头脑:

切换到备用登录屏幕。它有多个用户名和密码空白,确实出现但只有其中一个在正确的位置。字段名称是 RANDOM - 会话密钥随登录屏幕一起发送,然后服务器可以找出哪些字段是什么。成功或失败它然后被丢弃,因此您无法尝试重播攻击 - 如果您拒绝密码,他们将获得新的会话ID。

任何使用错误字段中的数据提交的表单都假定来自机器人 - 登录失败,句点,并且IP受到限制。确保随机字段名称永远不会与合法字段名称匹配,因此使用记住密码的内容的人不会误导。

接下来,如何使用不同类型的验证码:您有一系列不会给人类造成问题的问题。但是,它们 NOT 随机。当攻击开始时,每个人都会得到问题#1。一小时后问题#1被丢弃,永远不会再被使用,每个人都会得到问题#2,依此类推。

由于问题的一次性特性,攻击者无法探测下载数据库以放入他的机器人。他必须在一小时内向他的僵尸网络发送新指令,以便有能力做任何事情。

答案 12 :(得分:0)

由于有几个人将CAPTCHA作为一种后备人机制,我在CAPTCHA的有效性上添加了一个早期的StackOverflow问题和线程。

Has reCaptcha been cracked / hacked / OCR’d / defeated / broken?

使用CAPTCHA不会限制您的限制和其他建议的改进,但我认为包含CAPTCHA作为后备的答案数量应该考虑那些希望破坏安全性的人可用的基于人的方法。

答案 13 :(得分:0)

您还可以根据用户密码的强度进行限制。

当用户注册或更改密码时,您需要计算密码的强度等级,例如1到10之间。

像“密码”这样的东西得分为1,而“c6eqapRepe7et * Awr @ ch”可能得分为9或10,分数越高,限制开始的时间就越长。

答案 14 :(得分:0)

我在问这个问题时通常听到的第一个答案是更改端口,但忘了这一点,只需禁用IPv4即可。如果您只允许来自IPv6网络的客户端,您不再祈祷简单的网络扫描,攻击者将采用DNS查找。不要运行与Apache(AAAA)/ Sendmail(MX-&gt; AAAA)相同的地址/你给每个人(AAAA)的内容。确保您的区域不能被xferd,等待您允许任何人下载您的区域?

如果机器人发现您的服务器设置了新的主机名,只需在主机名前添加一些乱码,然后更改您的地址即可。保留旧名称,甚至设置僵尸网络的蜜罐名称为超时。

**测试您的反向(PTR)记录(在ip6.arpa。下)以查看它们是否可以用于在/ 4中具有VS / 4s记录的零。 I.E.通常情况下,ip6.arpa在一个地址中会有~32“。”s,但尝试使用最后几个丢失可能会避开具有记录的网络块VS其他没有记录的网络块。如果你进一步采用它,就可以跳过大部分地址空间。

在最糟糕的情况下,用户必须设置一个IPv6隧道,这并不像他们必须尽可能地进入DMZ ......虽然有人想知道为什么这不是第一个选择。

Kerberos也很酷,但IMHO LDAP打击(NISPlus在技术上有什么问题?我读过Sun认为用户想要LDAP,因此他们放弃了NIS +)。没有LDAP或NIS,Kerberos可以正常工作,只需要按主机管理主机上的用户。使用Kerberos为您提供了一种易于使用(如果不是自动化的)PKI。