什么是最好的分布式蛮力对策?
首先,有一点背景:我为CodeIgniter实现一个auth + auth系统并不是什么秘密,到目前为止,我赢了(可以这么说)。 但是我遇到了一个非常不平凡的挑战(大多数auth库完全错过了,但我坚持正确处理它):如何智能地处理大规模,分布式,可变用户名的暴力攻击 。
我知道所有常用的技巧:
- 限制每个IP /主机失败的尝试次数,并拒绝违法者访问(例如Fail2Ban) – 自从僵尸networking变得更加智能以来,
- 将上述内容与一个已知'坏'IP /主机 (例如DenyHosts) 黑名单 – 依靠僵尸networking#1, 他们越来越不
- 将IP /主机白名单与传统身份validation相结合(对于dynamicIP用户而言,可悲的是无用,大多数网站的stream量都很高)
- 在N分钟/小时的时间内设置一次站点范围内的失败尝试次数限制,并在此之后限制(暂停)所有login尝试,持续几分钟/小时(DoS攻击您的问题将成为僵尸networking玩家)
- 所有使用NOlogin/密码选项的用户的强制性数字签名 (公钥证书)或RSA硬件令牌(无疑是一个坚如磐石的解决scheme,但仅适用于封闭的专用服务)
- 强制使用超强密码scheme (例如> 25个带符号的无意义字符 – 对于临时用户来说又不切实际)
- 最后, CAPTCHA (可以在大多数情况下工作,但是对于用户来说很烦,对于一个坚定的,资源丰富的攻击者来说 实际上是无用的 )
现在,这些只是理论上可行的想法。 有很多垃圾的想法,打开网站(例如,微不足道的DoS攻击)。 我想要的是更好的东西。 我的意思是说:
-
它必须是安全的(+)反对DoS和powershell攻击,而不是引入任何新的漏洞,可能会让稍微偷偷摸摸的机器人继续在雷达下工作
-
它必须是自动的。 如果它需要人工操作员来validation每个login或监视可疑活动,它不会在真实世界的情况下工作
-
主stream网站的使用必须是可行的(即stream量大,stream量大,可以由非程序员进行开放注册)
-
它不能阻止用户体验到偶然用户会感到烦恼或沮丧(并可能放弃网站)
-
它不能涉及到小猫,除非它们真的很安全的小猫
(+) 以“安全”来说,我的意思是至less和偏执狂用户保密密码的能力一样安全
所以 – 让我们听听吧! 你会怎么做 ? 你知道我没有提到的最佳做法吗(噢,请说你这样做)? 我承认自己有自己的想法(把3和4的想法结合起来),但是我会让真正的专家在尴尬自己之前先说话;-)
好吧,足够拖延; 这是我到目前为止所做的
(对不起,很久以前,勇敢,朋友,旅程将是值得的)
将原始post中的方法3和4合并成一个“模糊”或dynamic白名单,然后 – 这就是诀窍 – 不会阻止非白名单的IP,只是将它们扼杀在地狱背后 。
请注意,这个措施只是为了阻止这种非常特殊的攻击。 当然,实际上,它可以与auth:auth:fixed-username throttling,per-IP节制,代码强制的强密码策略,未节制的cookielogin,在保存之前散列所有密码等价物的其他最佳实践方法结合使用,从不使用安全问题等
有关攻击情况的假设
如果攻击者瞄准variables用户名,我们的用户名限制不会触发。 如果攻击者正在使用僵尸networking或访问大量的IP范围,我们的IP节stream是无能为力的。 如果攻击者已经预先刮掉了我们的用户列表(通常可能在开放注册Web服务上),我们无法根据“用户未find”错误的数量来检测正在进行的攻击。 如果我们强制实行限制性系统(所有用户名,所有IP)限制,任何此类攻击都会在攻击期间加上限制期间阻止我们的整个站点。
所以我们需要做别的事情
第一部分对策:白名单
我们可以相当确定的是,攻击者无法检测并dynamic欺骗数千名用户(+)的IP地址。 这使得白名单变得可行。 换句话说:对于每个用户,我们存储用户以前(最近)login的(散列的)IP的列表。
因此,我们的白名单计划将作为一个locking的“前门”,用户必须从他的一个公认的“好”的IP连接才能login。 对这个“前门”的暴力攻击实际上是不可能的(+)。
(+),除非攻击者拥有服务器,所有用户的盒子或连接本身 – 在这种情况下,我们不再有“authentication”问题,我们有一个真正的特许经营规模的拉 – 插头FUBAR的情况
第二部分对策:系统范围内对无法识别的IP进行限制
为了使开放注册Web服务白名单工作,用户频繁地切换计算机和/或连接dynamicIP地址,我们需要为从未被识别的IP连接的用户开放“猫门”。 诀窍在于devise这个门让僵尸networking卡住,所以合法用户尽可能less地受到打扰。
在我的scheme中,这是通过设置一个非常限制的最大数量的未经批准的IPlogin尝试超过,例如,一个3小时的时间段(根据服务types使用更短或更长的时间可能更明智),以及使这个限制全球化 ,即。 为所有用户帐户。
即使是一个缓慢的(每次尝试之间1-2分钟)暴力也会被快速而有效地使用这种方法检测和阻止。 当然,一个真正缓慢的暴力仍然可以被忽视,但速度太慢击败暴力攻击的目的。
我希望通过这种节stream机制来实现的是,如果达到最大限度,我们的“猫门”就会closures一段时间,但是我们的前门仍然对通过常规方式连接的合法用户开放:
- 通过连接一个他们的公认的IP
- 或者通过使用持久logincookie(从任何地方)
在攻击过程中受到影响的唯一合法用户 – 而节stream被激活 – 将是没有持续logincookie的用户从未知位置或dynamicIPlogin。 这些用户将无法login,直到节stream消失(如果攻击者在节stream的情况下让他的僵尸networking继续运行,这可能需要一段时间)。
为了让这个小部分的用户能够通过密封的猫门挤走,即使机器人仍在凿击它,我也会使用带有validation码的“备份”login表单。 因此,当您显示“对不起,但您目前无法从此IP地址login”消息时,请包含一个链接,指出“ 安全备份login – 人为( 机器人:不说谎 ) ”。 开玩笑,当他们点击链接时,给他们一个reCAPTCHAauthentication的login表单,绕过整个网站的限制。 这样,如果他们是人类,并且知道正确的login名和密码(并且能够读取CAPTCHA),即使他们从未知主机连接而不使用自动logincookie,他们也不会被拒绝服务。
哦,只是为了澄清:因为我确实认为CAPTCHA通常是邪恶的,所以“备份”login选项只会 在节stream被激活时出现。
不可否认的是,这样的持续攻击仍然会构成DoS攻击的一种forms,但是对于所描述的系统而言,这只会影响我所怀疑的一小部分用户,也就是那些不使用“记住我”的cookie,恰好在攻击发生时login,并且没有从任何通常的IP地址login,也无法读取CAPTCHA。 只有那些能够拒绝所有这些标准的人 – 特别是机器人和真正不幸的残疾人 – 才会在机器人攻击时被拒绝。
编辑:实际上,我想到一种方法,即使在CAPTCHA挑战的用户在“locking”期间通过:而不是,或作为补充,备份validation码login,为用户提供一个单一的使用,用户特定的locking代码发送到他的电子邮件,他可以用来绕过节stream。 这肯定会超过我的“烦恼”的门槛,但是因为它只是用于一小部分用户的最后手段 ,而且由于它仍然被locking在帐户之外,所以这是可以接受的。
(另外请注意,如果攻击比我在这里描述的讨厌的分布式版本更加复杂,那么这种情况就不会发生,如果攻击来自less数几个IP地址,或者只打了几个用户名,它将会受到更多的阻碍,而且没有全站的后果)
所以,这就是我将在我的auth库中执行的对策,一旦我确信它是正确的,没有一个我已经错过的更简单的解决scheme。 事实上,在安全方面做错事情有很多微妙的方法,我不是在做错误的假设或者绝望的逻辑错误。 所以,请任何和所有的反馈,批评和改进,微妙之处等高度赞赏。
几个简单的步骤:
将某些常用用户名列入黑名单,并将其用作蜜jar。 pipe理员,客人等…不要让任何人用这些名字创build账户,所以如果有人尝试login他们,你就知道这是某人做某事他们不该做的事情。
确保网站上有实力的人拥有安全的密码。 要求pipe理员/pipe理员使用字母,数字和符号组合的较长密码。 拒绝来自普通用户的简单密码,并加以解释。
你可以做的最简单的事情之一是告诉人们有人试图login他们的账户,并给他们一个链接来报告事件,如果不是他们。 一个简单的信息,当他们login像“有人试图login到您的帐户星期三凌晨4点20分等等,点击这里,如果这不是你。 它可以让你保留一些攻击统计。 如果您发现欺诈访问突然增加,您可以加强监控和安全措施。
如果我正确理解powershell攻击的MO,则会连续尝试一个或多个用户名。
有两个build议,我不认为我在这里看过:
- 我一直认为标准的做法是在每个用户错误的login后有一个短暂的延迟(大约一秒钟)。 这阻碍了蛮力,但是我不知道一秒钟的延迟能够维持字典攻击的时间。 (10000字的字典== 10000秒==约3小时,嗯,不够好)
- 而不是一个网站的速度减慢,为什么不是一个用户名的节stream。 油门变得越来越苛刻,每次错误的尝试(达到一个极限,我想所以真正的用户仍然可以login)
编辑 :为了响应用户名油门的意见:这是一个用户名特定的油门,不考虑攻击的来源。
如果用户名受到限制,那么即使是协调的用户名攻击(多IP,单个猜测每个IP,相同的用户名)也会被捕获。 即使攻击者在超时期间可以自由尝试其他用户/密码,个别用户名也受到限制。
从攻击者的angular度来看,在暂停期间,您可能会首先猜测100个密码,并快速发现每个帐户有一个错误的密码。 您可能只能在同一时间段内进行50秒的猜测。
从用户帐户的angular度来看,即使猜测来自多个来源,仍然需要相同的平均猜测次数来破解密码。
对于攻击者来说,最好的做法是打破100个账户,尽pipe这个账户是1个账户,但是由于你并不是在站点范围内进行节stream,所以你可以很快加速。
额外的改进:
- 检测猜测多个帐户的IP – 408请求超时
- 检测猜测同一个帐户的IP – 408大数(例如100)猜测之后的请求超时。
用户界面的想法(可能不适合在这种情况下),这也可以改进上述:
- 如果你是在控制密码设置,那么向用户显示密码的强度是鼓励他们select一个更好的密码 。
- 如果您在login页面的控制之下,在一个简单的(比如说10个)单个用户名猜测之后,提供一个CAPTCHA。
有三个身份validation因素:
- 用户知道某事(即密码)
- 用户有一些东西(即,钥匙链)
- 用户是东西(即视网膜扫描)
通常,网站只执行策略#1。 即使大多数银行只执行政策1.他们反而依靠一个“知道别的办法”来双因素authentication。 (IE:用户知道他们的密码和他们母亲的婚前姓名)如果可以的话,添加第二个authentication因素的方法不是太困难。
如果可以生成大约256个随机性字符,则可以将其构造成16×16的表格,然后例如要求用户给出单元格A-14的表格中的值。 当用户注册或更改密码时,将表格给他们,告诉他们将其打印出来并保存。
这种方法的困难在于,当用户忘记密码时,他们不会仅仅提供标准的“回答这个问题并且input一个新的密码”,因为这样也容易受到暴力的威胁。 此外,您不能重置它,并发送给他们一个新的,因为他们的电子邮件可能会受到影响。 (请参阅:Makeuseof.com及其被盗域名。)
另一个想法(涉及小猫),是BOA所谓的SiteKey(我相信他们的商标名)。 简而言之,您有用户在注册时上传图片,当他们尝试login时,要求他们从8个或15个(或更多)随机的图片中挑选图片。 因此,如果用户上传他们的小猫的图片,理论上只有他们确切地知道哪个图片是其他小猫(或花或其他)的图片。 这种方法唯一真正的可靠性是中间人攻击。
另一个想法是,追踪用户访问系统的IP地址,并要求他们在从他们避难的地址login时执行额外的身份validation(captcha,挑选一个小猫,从这个表中select一个密钥)之前。 另外,类似于GMail,允许用户查看他们最近login的地方。
编辑,新想法:
validationlogin尝试的另一种方法是检查用户是否来自您的login页面。 你不能检查推荐人,因为他们可以很容易伪造。 您需要在用户查看login页面时在_SESSION var中设置一个键,然后在提交login信息时检查是否存在键。 如果bot没有从login页面提交,将无法login。 你也可以通过在这个过程中使用javascript来设置一个cookie,或者在加载之后向表单中添加一些信息。 或者,您可以将表单分成两个不同的提交(即,用户input他们的用户名,提交,然后在新的页面上input他们的密码,然后再次提交。)
在这种情况下,关键是最重要的一个方面。 生成它们的常用方法是用户数据,IP地址和提交时间的一些组合。
我必须问你是否已经对这个问题进行了成本效益分析。 这听起来像是在试图保护自己免受攻击者的攻击,因为他们有足够的networking来猜测一些密码,每个IP发送3-5个请求(因为你已经解除了IP限制)。 这种攻击会花费多less(大致)? 是否比您要保护的账户的价值更贵? 有多less庞大的僵尸networking需要你拥有的?
答案可能不是 – 但如果是这样的话,我希望你能从某种安全专业人员那里得到帮助; 编程技巧(和StackOverflow得分)与安全技术诀窍没有很强的关联。
将Jens的scheme归纳为伪状态转换图/规则库:
- 用户名+密码 – >input
- 用户+!密码 – >拒绝
- 用户+ known_IP(用户) – >前门,
// never throttle
- 用户+ unknown_IP(用户) – > catflap
- (#denied> n)通过catflaps(站点) – >油门catflaps(站点)
// slow the bots
- catflap +油门+密码+ captcha – >进入
// humans still welcome
- catflap +油门+密码+!captcha – >拒绝
// a correct guess from a bot
观察:
- 切勿油门前门。 埃尔邦国家警察在你家里有你的电脑,但无法审问你。 蛮力是你的电脑可行的方法。
- 如果您提供“忘记密码?” 链接,那么您的电子邮件帐户成为攻击面的一部分。
这些意见涵盖了一个不同types的攻击,你正试图对抗。
我以前回答了一个非常类似的问题, 我怎样才能限制在PHP中的用户login尝试 。 我将在这里重申所提出的解决scheme,因为我相信你们中的许多人会发现它的信息和有用的看到一些实际的代码。 请记住,使用CAPTCHA可能不是最好的解决scheme,因为现在CAPTCHA攻击者正在使用越来越精确的algorithm:
您不能简单地通过将节stream链接到单个IP或用户名来防止DoS攻击。 地狱,你甚至不能真正防止使用这种方法的快速login尝试。
为什么? 由于攻击可以跨越多个IP和用户帐户,以绕过您的限制尝试。
我已经在其他地方看到过,理想情况下,您应该跟踪整个网站上所有失败的login尝试,并将它们与时间戳相关联:
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;
根据给定时间内login失败的总次数确定某些延迟。 您应该根据从您的failed_logins
表中提取的统计数据,因为它会根据用户数量以及他们可以调用(和键入)其密码的数量随时间变化 。
10 failed attempts = 1 second 20 failed attempts = 2 seconds 30 failed attempts = reCaptcha
在每次失败的login尝试中查询表,以查找给定时间段(例如15分钟)的失败login次数:
SELECT COUNT(1) AS failed FROM failed_logins WHERE attempted > DATE_SUB(NOW(), INTERVAL 15 minute);
如果在给定时间段内的尝试次数超过了您的限制,则强制执行限制或强制所有用户使用validation码(即,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在一定的阈值将确保多方面的攻击将被最小化 ,正常的站点用户不会经历合法的失败login尝试显着的延迟。 我不能保证预防,因为已经扩大了CAPTCHA的可能性。 还有其他的解决办法,可能是“命名这个动物”的一个变种,这个变种可以很好地作为替代品。
看起来你正在试图抵御慢分布的蛮力 。 不是你可以做的。 我们正在使用PKI并且没有密码login。 这有帮助,但是如果你的客户每隔一段时间偶然的工作站,这是不适用的。
免责声明:我为双重身份的公司工作,但不是在这里插上它。 这里有一些观察。
XSS和浏览器恶意软件可能会窃取Cookies。 用户通常会更改浏览器或清除Cookie。
源IP地址同时是dynamicvariables和可伪造的。
validation码是有用的,但不authentication特定的人。
多种方法可以成功结合,但好味道肯定是有序的。
密码的复杂性是很好的,任何基于密码的密码依赖于具有足够熵的密码。 恕我直言,强大的密码写在一个安全的物理位置比在内存中的弱密码更好。 人们知道如何评估纸质文档的安全性,比用三个不同的网站作为密码的时候知道如何计算他们狗的名字中的有效熵更好。 考虑让用户能够打印出一次性使用密码的大小页面。
像“你的高中吉祥物是什么”这样的安全问题大多是另外一种“你知道的东西”的糟糕forms,其中大多数在公共领域很容易被猜测或者完全无法理解。
正如您所指出的那样,限制失败的login尝试是防止暴力攻击和简化DoSing帐户之间的折衷。 积极的locking政策可能反映了对密码熵缺乏信心。
我个人并不认为在网站上强制实施密码到期的好处。 攻击者一次获得你的密码,然后他可以改变它,并尽可能简单地遵守该政策。 也许一个好处是,如果攻击者改变了账号密码,用户可能会注意到更快。 更好的办法是在攻击者获得访问权之前通知用户。 诸如“自从上次login以来N次尝试失败”的消息在这方面是有用的。
最好的安全来自第二个身份validation,这个身份是第一个带外的。 就像你说的那样,硬件令牌在“你有的东西”是好的,但是许多(不是全部)有真正的pipe理开销与他们的分配有关。 我不知道任何生物识别“你是什么”的网站解决scheme。 一些双因素解决scheme可以与openid提供商合作,其中一些提供PHP / Perl / Python SDK。
不pipe你的系统有多好,在一个足够长的时间内都会失败。 这里有一些好主意,关于如何延长密码的持续时间。 (我个人喜欢每个用户和每个IP地址的指数增长尝试速度限制的想法。)但是不pipe你怎么做,你都需要用一些密码规则来备份它。
我鼓励你弄清楚密码破解的速度有多快,并且让用户改变密码的次数。 希望这可以帮助。
编辑:如果你期望很多懒惰的攻击者,多次失败尝试后需要一些CAPTCHA是好的:它提高了一点吧。 如果你担心很多聪明的攻击者,请聘请安全顾问。 ;)
我最高的build议是,只要确保让用户知道他们的账户login尝试不良,用户可能会更加认真地对待他们的密码,只要他们提供证据表明有人正在尝试进入他们的账户。
实际上,我发现有人攻击了我兄弟的myspace账户,因为他们试图进入我为他设置的Gmail账户,并使用“通过电子邮件重置我的密码”function…这是我的收件箱。
-
在input正常密码之前需要一次性密码? 这将使得很明显,有人在获得许多机会猜测主密码之前进行攻击?
-
保持全球统计/login失败率 – 这是攻击的指标 – 在攻击期间更严格地login失败,例如更快地禁止IP。
我不相信有一个完美的答案,但我会倾向于在试图混淆机器人的基础上接近它,如果感受到攻击。
关于我的头脑:
切换到备用login屏幕。 它有多个用户名和密码空白确实出现,但只有其中一个是在正确的地方。 字段名称是随机的 –会话密钥随login屏幕一起发送,然后服务器可以找出哪些字段是什么。 成功或失败它被丢弃,所以你不能尝试重播攻击 – 如果你拒绝密码,他们会得到一个新的会话ID。
任何与错误字段中的数据一起提交的表单被假定为来自机器人 – login失败,句点,并且IP被限制。 确保随机字段名称从不匹配合法字段名称,以便使用某些记住密码的人不会误导。
接下来,怎么样一个不同的validation码:你有一系列的问题,不会对人类造成问题。 但是,它们不是随机的。 当攻击开始时,每个人都被给予问题#1。 一小时之后,问题#1被丢弃,永远不会再被使用,每个人都会问#2等等。
由于问题的一次性性质,攻击者不能探测下载数据库放入他的机器人。 他必须在一个小时之内向他的僵尸networking发出新的指示,以便有能力做任何事情。
由于有几个人把CAPTCHA作为回退的人机制,所以我添加了一个较早的StackOverflow问题和关于CAPTCHA的有效性的线程。
reCaptcha是否被破解/黑客入侵/ OCR已被破解?
使用CAPTCHA不会限制你的调节和其他build议的改进,但是我认为包括CAPTCHA在内的答案的数量应该考虑基于人类的方法来提供给打破安全性的人们。
您还可以基于用户密码的强度进行限制。
当用户注册或更改密码时,您可以计算他们的密码的强度等级,比如介于1和10之间。
像“密码”分数为1,而“c6eqapRepe7et * Awr @ ch”可能得分9或10,分数越高,加速时间越长。
我问这个问题时通常听到的第一个答案是改变端口,但忘记了这一点,只是禁用IPv4。 如果您只允许来自IPv6networking的客户端,那么您将不再为简单的networking扫描工作祈祷,攻击者将使用DNS查找。 不要运行在与Apache(AAAA)/ Sendmail(MX-> AAAA)相同的地址/您向每个人发送了什么(AAAA)。 确保你的区域不能是xferd,等待你的区域被任何人下载?
如果机器人发现你的服务器设置了新的主机名,只要在你的主机名上添加一些乱码,然后改变你的地址即可。 留下旧的名称,甚至设置蜜jarnetworking的蜜jar名称超时。
**testing你的反向(PTR)logging(在ip6.arpa下),看看它们是否可以被用来在有/没有logging的VS / 4的logging中使用。 IE通常ip6.arpa在一个地址中有32个“s”,但是在最后几个失踪的情况下尝试可能会避开有logging的networking块VS其他networking块。 如果进一步考虑,可以跳过大部分的地址空间。
在最糟糕的情况下,用户将不得不build立一个IPv6隧道,而不必像VPN一样进入DMZ区。尽pipe人们想知道为什么这不是第一个select。
另外,Kerberos也很酷,但是IMHO LDAP(NISPlus在技术上有什么错误?我读过Sun认为用户想要LDAP,因此他们放弃了NIS +)。 Kerberos可以在没有LDAP或NIS的情况下正常工作,只需要根据主机pipe理主机上的用户。 使用Kerberos可以让您轻松使用(如果不是自动的话)PKI。
在这里迟了一点,但我想,假设一个困难的情况 – 攻击者使用大量的随机IP,随机的用户名和一个随机的密码,从10,000个最stream行的列表中select。
有一件事你可以做,特别是如果系统似乎受到攻击,因为系统上有很多错误的密码尝试,尤其是如果密码是低熵的问题是要问一个第二个问题,例如你父母的名字是什么,例如。 如果一个攻击者攻击了一百万个试图使用密码“password1”的账户,那么他们很可能会获得很多的机会,但是他们获得正确名称的可能性会大大降低成功率。