代码之家  ›  专栏  ›  技术社区  ›  Jens Roland

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

  •  143
  • Jens Roland  · 技术社区  · 17 年前

    我知道所有的惯用伎俩:

    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. 最后, (这在大多数情况下都可以工作,但对用户和 virtually useless 反对 determined, resourceful attacker

    现在,这些只是理论上可行的想法。有 大量 垃圾的想法,把网站炸开了(例如,琐碎的拒绝服务攻击)。我想要的是更好的。我所说的更好是指:

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

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

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

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

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

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

    17 回复  |  直到 17 年前
        1
  •  71
  •   Jens Roland    17 年前

    好了,别再拖延了;这是我到目前为止的想法

    (对不起,前面还有很长的路要走。勇敢点,朋友,这趟旅程是值得的)

    不是阻止未列入白名单的IP,只是将它们限制在地狱和地狱之间 .

    请注意,此度量是 只有 旨在挫败这种特殊类型的攻击。当然,在实践中,它将与其他身份验证最佳实践方法结合使用:固定用户名限制、每IP限制、代码强制的强密码策略、无限制cookie登录、保存密码前对所有密码等价项进行哈希处理、从不使用安全问题等。

    如果攻击者以可变用户名为目标,则不会触发用户名限制。如果攻击者正在使用僵尸网络或访问较大的IP范围,则我们的IP限制是无能为力的。如果攻击者预先抓取了我们的用户列表(通常可能在开放注册web服务上),我们无法根据“未找到用户”错误的数量检测到正在进行的攻击。如果我们强制实施限制性的系统范围(所有用户名、所有IP)限制,任何此类攻击都会在攻击期间加上限制期内关闭整个站点。

    所以我们需要做些别的事情。

    对策的第一部分:白名单

    我们可以相当肯定的是,攻击者无法检测并动态欺骗数千名用户(+)的IP地址。这使得 白名单 可行的换句话说:对于每个用户,我们存储用户以前(最近)登录的(散列)IP列表。

    (+)除非攻击者“拥有”服务器、所有用户的盒子或连接本身——在这些情况下,我们不再有“身份验证”问题,否则我们将面临真正的“拔掉插头”的情况

    对策的第二部分:全系统节流 未识别IP的数量

    为了使白名单适用于开放注册web服务,用户经常切换计算机和/或通过动态IP地址连接,我们需要为从未识别IP连接的用户打开“猫门”。诀窍是设计这扇门,让僵尸网络卡住,让合法用户感到烦恼 尽可能少 .

    在我的方案中,这是通过设置 非常 限制未经批准的IP在3小时内尝试登录失败的最大次数(根据服务类型,使用更短或更长的时间可能更明智),并作出限制 全球的 ,即适用于所有用户帐户。

    使用此方法,即使是缓慢(尝试间隔1-2分钟)的暴力也会被快速有效地检测和挫败。当然,一个 蛮力仍然可以不被注意,但是太慢的速度破坏了蛮力攻击的目的。

    我希望通过这种节流机制实现的是,如果达到最大限制,我们的“猫门”会关闭一段时间,但我们的前门仍然对通过常规方式连接的合法用户开放:

    • 或者使用持久登录cookie(从任何地方)

    在攻击期间(即在节流被激活时)唯一会受到影响的合法用户将是没有持久登录cookie的用户,他们从未知位置登录或使用动态IP登录。这些用户将无法登录,直到节流消失(如果攻击者在节流的情况下仍保持其僵尸网络运行,这可能需要一段时间)。

    为了让这一小部分用户挤过原本密封的猫门,即使机器人还在使劲敲打,我会使用带有验证码的“备份”登录表单。因此,当您显示“抱歉,但您目前无法从此IP地址登录”消息时,请包含一个链接 安全备份登录-仅限人员( 机器人:不要说谎 ) “。撇开玩笑不说,当他们点击该链接时,给他们一个reCAPTCHA认证的登录表单,绕过站点范围的限制。这样,如果他们是人,知道正确的登录+密码(并且能够读取CAPTCHA),他们将 从不 被拒绝服务,即使他们是从未知主机连接并且没有使用autologin cookie。

    哦,我想澄清一下:因为我确实认为CAPTCHA通常是邪恶的,所以“备份”登录选项将 显得 当节流处于活动状态时 .

    不可否认,像这样的持续攻击仍然会构成DoS攻击的一种形式,但在所描述的系统就绪的情况下,它只会影响我怀疑的一小部分用户,即不使用“记住我”的用户cookie和碰巧在发生攻击时登录,并且没有从任何常用IP登录,并且无法读取CAPTCHA。只有那些能够拒绝所有这些标准的人——特别是机器人和机器人 真倒霉

    编辑: 实际上,我想到了一种方法,即使是验证码有问题的用户也可以在“锁定”过程中通过:代替备份验证码登录,或者作为备份验证码登录的补充,为用户提供一个选项,让用户将一个单次使用的、特定于用户的锁定代码发送到他的电子邮件,然后他可以使用该代码绕过限制。这肯定超过了我的“烦恼”阈值,但因为它只是用作 对于一小部分用户来说,由于这仍然比被锁定在您的帐户之外要好,所以这是可以接受的。

    (另外,请注意 没有一个 如果攻击没有我在这里描述的糟糕的分布式版本那么复杂,就会发生这种情况。如果攻击只来自几个IP或只涉及几个用户名,那么它将在更早的时候被挫败,并且 现场范围的后果)


        2
  •  17
  •   patros    17 年前

    几个简单的步骤:

    确保任何在网站上有实权的人都有一个安全的密码。要求管理员/版主拥有更长的密码,密码中包含字母、数字和符号。拒绝普通用户提供的简单密码,并给出解释。

    你能做的最简单的事情之一就是告诉人们有人试图登录他们的帐户,如果不是他们,给他们一个报告事件的链接。 当他们登录时,会显示一条简单的消息,比如“有人试图在周三凌晨4:20登录你的帐户,诸如此类。如果不是你,请单击此处。”它可以让你保存一些攻击统计信息。如果发现欺诈性访问突然增加,您可以加强监控和安全措施。

        3
  •  11
  •   jamesh    17 年前

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

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

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

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

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

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

    额外改进:

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

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

    • 如果您控制密码设置,则显示用户 how strong their password is 鼓励他们选择一个更好的。
    • 如果您可以控制登录 ,在对单个用户名进行少量(比如10次)猜测后,提供验证码。
        4
  •  9
  •   Balaji Kandasamy    12 年前

    认证有三个因素:

    1. 使用者 某物(即密码)
    2. 使用者 某物(如钥匙)
    3. 使用者 某些东西(如视网膜扫描)

    通常,网站只执行策略1。即使是大多数银行也只执行政策1。相反,他们依靠“知道其他东西”的方法进行双因素身份验证。(即:用户知道自己的密码和母亲的娘家姓。)如果可以,添加第二个身份验证因素的方法并不太困难。

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

    这种方法的困难在于,当用户忘记密码时,你不能只提供标准的“回答这个问题并输入一个新密码”,因为这也容易受到暴力的攻击。另外,你不能重置它并给他们发一封新的邮件,因为他们的邮件也可能被泄露。(请参阅:Makeuseof.com及其被盗域名。)

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

    编辑,新想法:

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

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

        5
  •  7
  •   Community Mohan Dere    9 年前

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

    您不能简单地通过将限制链接到单个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 尽管如此


    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);
    

    如果给定时间段内的尝试次数超过您的限制,请强制限制或强制所有用户使用captcha(即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将确保从多个前线发起的攻击不会受到影响 最小化 正常的站点用户不会因为合法的失败登录尝试而经历重大延迟。我不能保证预防,因为它已经被扩展了,验证码可以被破坏。还有其他的解决方案,也许是“命名这种动物”的变体,可以很好地作为替代品。

        6
  •  6
  •   ojrac    17 年前

    我要问你是否对这个问题做过成本效益分析;这听起来像是你在试图保护自己免受攻击者的攻击,因为攻击者有足够的网络状态来猜测密码的数量,每个IP可能发送3-5个请求(因为你已经取消了IP限制)。这种攻击大概要花多少钱?它是否比您试图保护的帐户的价值更昂贵?有多少庞大的僵尸网络想要你拥有的?

        7
  •  5
  •   jamesh    17 年前

    要将Jens的方案总结为伪状态转换图/规则库,请执行以下操作:

    1. 用户+密码->进入
    2. 用户+!密码->否认
    3. 用户+已知IP(用户)->;前门, // never throttle
    4. 用户+未知\u IP(用户)->;猫皮瓣
    5. // slow the bots
    6. catflap+油门+密码+验证码->进入 // humans still welcome
    7. 油门+油门+密码+!验证码->否认 // a correct guess from a bot

    • 千万不要关前门。厄尔本州警方在你家里有你的电脑,但无法审问你。暴力是一个可行的方法,从您的计算机。
    • 如果您提供“忘记密码”链接,则您的电子邮件帐户将成为攻击面的一部分。

    这些观察涵盖了与您试图反击的攻击不同的攻击类型。

        8
  •  4
  •   raupach    17 年前

    slow distributed brute force . 你对此无能为力。我们使用的是PKI,没有密码登录。这是有帮助的,但是如果你的客户偶尔有机会使用工作站,这就不太适用了。

        9
  •  3
  •   Marsh Ray    17 年前

    免责声明:我在一家双因素公司工作,但我不是来这里插上插头的。以下是一些观察结果。

    源IP地址同时是动态可变和伪造的。

    验证码很有用,但不能验证特定的人。

    密码的复杂性是好的,任何基于密码的东西都取决于密码是否具有足够的熵。依我看,在一个安全的物理位置写下一个强密码比在内存中写下一个弱密码要好。人们知道如何评估纸质文档的安全性,而不知道如何计算狗名中的有效熵,当狗名用作三个不同网站的密码时。考虑让用户有能力打印一个大的或小的页面,其中满是一次性使用的通行码。

    像“你的高中吉祥物是什么”这样的安全问题大多是“你知道的事情”的另一种糟糕形式,大多数问题都很容易猜到,或者是公开的。

    正如您所注意到的,阻止失败的登录尝试是防止暴力攻击和轻松添加帐户之间的权衡。主动锁定策略可能反映出对密码熵缺乏信心。

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

        10
  •  1
  •   nvuono    17 年前

    我的最高建议是确保你 随时通知用户 对其帐户进行错误登录尝试的次数-- 如果有证据表明有人试图进入他们的帐户,用户可能会更认真地对待他们的密码强度。

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

        12
  •  0
  •   Loren Pechtel    17 年前

    在我的脑海里:

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

    提交的任何表单中包含错误字段中的数据都被假定为来自robot——登录失败,并且IP被限制。确保随机字段名永远不会与合法字段名匹配,这样使用记住密码的东西的人就不会被误导。

    接下来,换一种验证码怎么样:你有一系列不会给人带来麻烦的问题。然而,它们是 随机的当攻击开始时,每个人都会被问到问题1。一小时后,问题1被丢弃,不再使用,每个人都会得到问题2,以此类推。

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

        13
  •  0
  •   Community Mohan Dere    9 年前

    由于一些人将CAPTCHA作为一种备用的人工机制,我在前面添加了一个关于CAPTCHA有效性的StackOverflow问题和线程。

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

    使用CAPTCHA不会限制您的节流和其他建议,但我认为包含CAPTCHA作为回退的答案应该考虑基于人的方法,以寻找破坏安全性的人。

        14
  •  0
  •   Joseph W    15 年前

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

    类似“password”的分数为1,而“c6eqapRepe7et”的分数为1*Awr@ch“可能得9分或10分,分数越高,节流启动所需的时间越长。

        15
  •  0
  •   Mike Mestnik    11 年前

    问这个问题时,我通常听到的第一个答案是更改端口,但忘记这一点,只需禁用IPv4即可。如果您只允许来自IPv6网络的客户端,那么您就不再需要简单的网络扫描,攻击者将求助于DNS查找。不要在与您的Apache(AAAA)/Sendmail(MX->AAAA)/what have out to Everyone(AAAA)相同的地址上运行。确保你的区域不能被xferd,等等,你是否允许任何人下载你的区域?

    如果机器人发现你的服务器设置了新的主机名,只需在你的主机名前加上一些乱码,然后更改你的地址。保留旧名称,甚至设置**蜜罐名称,以便机器人网络超时。

    **测试您的反向(PTR)记录(在ip6.arpa下),看看它们是否可以用于在有记录的/4和没有记录的/4上归零。也就是说,通常ip6.arpa在一个地址中会有32个“.”,但尝试使用最后几个丢失的地址可能会避开有记录的网络块,而其他没有记录的网络块则可能会出现这种情况。如果再进一步,就有可能跳过大部分地址空间。

    在最坏的情况下,用户将不得不设置一个IPv6隧道,这不像他们必须走到一个DMZ的VPNing那么远。。。尽管有人想知道为什么这不是第一个选择。

    Kerberos也很酷,但是IMHO LDAP失败了(NISPlus在技术上有什么问题?我读到Sun决定用户需要LDAP,因此他们放弃了NIS+)。Kerberos在没有LDAP或NIS的情况下运行良好,只需逐个主机管理用户即可。使用Kerberos可以为您提供一个易于使用(如果不是自动化的话)的PKI。

        16
  •  0
  •   Tim 333    10 年前

    这里有点晚了,但我在想,假设一个很难的情况-攻击者使用大量随机IP、随机用户名和随机密码,这些都是从10000个最流行的IP列表中选择的。