为啥检查错误的密码比检查正确的密码要花更长的时间?

Posted

技术标签:

【中文标题】为啥检查错误的密码比检查正确的密码要花更长的时间?【英文标题】:Why should checking a wrong password take longer than checking the right one?为什么检查错误的密码比检查正确的密码要花更长的时间? 【发布时间】:2010-10-17 06:35:37 【问题描述】:

这个问题一直困扰着我。

在 Linux 上,当要求输入密码时,如果您的输入正确,它会立即检查,几乎没有延迟。但是,另一方面,如果您输入了错误的密码,则需要更长的时间来检查。这是为什么呢?

我在尝试过的所有Linux distributions 中都观察到了这一点。

【问题讨论】:

您会发现 Windows 也是如此。此外,将标题更改为“为什么错误的密码比正确的密码需要更长的时间”。会让它与编程更相关。 我刚刚登录了我的 Ubuntu 系统,输入了错误的密码并问了自己同样的问题。 :-) 【参考方案1】:

这实际上是为了防止暴力攻击每秒尝试数百万个密码。这个想法是限制检查密码的速度,并且应该遵循一些规则。

成功的用户/密码对应立即成功。 应该没有可以检测到的失败原因有明显差异。

最后一个特别重要。这意味着没有有用的消息,例如:

Your user name is correct but your password is wrong, please try again

或:

Sorry, password wasn't long enough

“无效用户和密码”和“有效用户但无效密码”失败原因的响应甚至没有时间差。

每一个失败都应该提供完全相同的信息,无论是文本的还是其他的。

有些系统更进一步,每次失败都会增加延迟,或者只允许三个失败然后在允许重试之前有很大的延迟。

【讨论】:

这如何防止应用分叉,尝试输入密码,如果它在一段时间内没有返回成功,杀死 -9 的孩子并再次分叉。是的,仅当您可以以某些用户身份登录时才有效,但是什么时候阻止了任何人? 它不会阻止任何人,但您仍然需要延迟“一段时间”。即使是微小的延迟也会使检查数百万个密码变得毫无用处,如果您在登录时这样做,被检测到 - 您认为登录失败不会记录任何内容吗? BCS:如果您已经有一个有效的登录名并有足够的权限来执行您的建议,那么您可能不再需要暴力攻击(因为您可以使用其他攻击媒介)。延迟对外部攻击者最有用。【参考方案2】:

这使得猜测密码需要更长的时间。

【讨论】:

【参考方案3】:

我不确定,但在输入错误密码后集成延迟以增加攻击难度是很常见的。这使得攻击实际上不可行,因为只检查几个密码需要很长时间。

即使尝试几个密码——生日、猫的名字等等——也变得毫无乐趣。

【讨论】:

通常第二次失败的超时时间比第一次的超时时间长——这也很好。 您是否看到有关最有可能密码的新闻帖子? 123456非常非常受欢迎! @Spence,我确实看到了这些项目,但从记忆中,它并不像人们所说的那么糟糕,他们(正如媒体惯常做的那样)把它吹得不成比例。密码是从在线发现的已泄露帐户列表中提取的,这意味着它们更有可能是不安全的(因为它们已被泄露)。 123456 可能很好占受感染帐户的 30%(例如),但在所有帐户中不太可能接近那么重要。 不,这些列表来自密码数据库黑客,其中大多数代表数百万的样本集。这些黑客攻击的结果已在多个在线数据集中得到证实,并且高度代表“普通”消费者。获得更好密码的唯一方法是在创建时强制执行它,或者更好的是使用更有用的 2 因素身份验证。【参考方案4】:

基本上是为了减轻暴力破解和字典攻击。

来自The Linux-PAM Application Developer's Guide:

计划延误

extern int pam_fail_delay(pam_handle_t *pamh, unsigned int micro_sec);

此功能由 Linux-PAM 提供 以方便以下的时间延迟 调用 pam_authenticate() 失败和 在控制权返回到 应用。使用此功能时 应用程序员应该 检查它是否可用,

#ifdef PAM_FAIL_DELAY
    ....
#endif /* PAM_FAIL_DELAY */

通常,应用程序请求 用户通过了身份验证 Linux-PAM 通过调用 pam_authenticate() 或 pam_chauthtok()。 这些函数调用每个 列出了堆叠的身份验证模块 在相关的 Linux-PAM 配置文件。按照指示 此文件,多个模块之一 可能会导致 pam_...() 调用失败 返回错误。这是可取的 之前也有一个停顿 申请继续。校长 这种延迟的原因是安全性:a 延迟行为以阻止蛮力 字典攻击主要是,但也 有助于阻碍定时(隐蔽通道) 攻击。

【讨论】:

【参考方案5】:

这是一种非常简单、几乎不费吹灰之力的方法,可以大大提高安全性。考虑:

    系统A 没有延迟。攻击者有一个创建用户名/密码组合的程序。以每分钟数千次尝试的速度,尝试每个组合并记录所有成功登录只需要几个小时。

    系统 B 在每次猜错后产生 5 秒延迟。攻击者的效率已降低到每分钟 12 次尝试,有效地削弱了蛮力攻击。而不是几个小时,它可能需要几个月才能找到有效的登录。如果黑客是那样的耐心,他们就会变得合法。 :-)

【讨论】:

【参考方案6】:

身份验证失败延迟是为了降低登录尝试率。如果有人尝试对一个或可能的用户帐户进行字典或暴力攻击,则攻击者将需要等待失败延迟,从而迫使他花费更多时间,让您有更多机会检测到它。

您可能还想知道,根据您使用的登录 shell,通常有一种方法可以配置此延迟。

在 GDM 中,延迟设置在 gdm.conf 文件中(通常在 /etc/gdm/gdm.conf 中)。您需要设置 RetryDelay=x 其中 x 是以秒为单位的值。

现在大多数 linux 发行版还支持在 /etc/login.defs 中定义 FAIL_DELAY,允许您在登录尝试失败后设置等待时间。

最后,PAM 还允许您在身份验证行上设置 nodelay 属性以绕过失败延迟。 (Here's an article on PAM and linux)

【讨论】:

【参考方案7】:

我不认为它可以像回复所暗示的那样简单。

如果对正确密码的响应是立即的(某个值),您是否只需要等到超过该值才能知道密码错误? (至少从概率上知道,这对于破解目的来说很好)而且无论如何你会并行运行这个攻击......这就是一个大的 DoS 欢迎垫吗?

【讨论】:

这不是他们的意思。密码错误或正确之间有明显的区别。他们的意思是不正确的用户名和不正确的密码之间应该没有区别。你的意思是并行运行这种攻击吗?如何并行运行? @Mark,并行运行可能需要打开多个连接并尝试登录。仍然很耗时,而且不太实用。 如果您可以在非慢速连接上每秒运行一百万次检查,然后该连接为失败的尝试添加了 1 秒的延迟,那么您需要一百万个攻击客户端才能获得相同的结果影响。我怀疑服务器是否允许创建这么多的 telnet 会话。 重点是不用等到延迟之后再尝试下一个密码,那有什么用呢? @Greg,你必须重新连接到主机,如果有必要,下一步是检查 IP 地址以捕获它。【参考方案8】:

我之前尝试过的方法似乎有效,但实际上没有;如果您在意,您必须查看 wiki 编辑历史记录...

作用(对我而言)是,both 降低 /etc/pam.d/login 中 pam_faildelay.so delay=X 的值(我将它降低到 500000,半秒),并且还common-auth 的行尾添加 nodelay(前面有一个空格) ,正如 Gabriel 在他的回答中所描述的那样。

auth [success=1 default=ignore] pam_unix.so nullok_secure nodelay

至少对我(debian sid)而言,仅进行其中一项更改不会将延迟明显缩短到默认 3 秒以下,尽管可以通过仅更改 /etc/pam.d 中的值来延长延迟/登录。

这种废话足以让一个成年人哭泣!

【讨论】:

【参考方案9】:

在 Ubuntu 9.10 上,我也认为是新版本,您要查找的文件位于

/etc/pam.d/login

编辑该行:

auth 可选 pam_faildelay.so 延迟=3000000

将数字 3 更改为您可能想要的另一个数字。

请注意,要进行“nodelay”身份验证,我认为您应该编辑文件

/etc/pam.d/common-auth

也是。上线:

auth [success=1 default=ignore] pam_unix.so nullok_secure

将“nodelay”添加到最后(不带引号)。 但我认为这是关于“nodelay”的最终解释。

【讨论】:

【参考方案10】:

我想从开发人员的角度添加一个注释。虽然这对肉眼来说并不明显,但聪明的开发人员会在找到匹配项时打破匹配查询。在见证中,成功的匹配比失败的匹配完成得更快。因为,匹配函数会将凭据与所有已知帐户进行比较,直到找到正确的匹配项。换句话说,假设有 1,000,000 个按 ID 排列的用户帐户; 001、002、003 等等。您的 ID 是 43,001。因此,当您输入正确的用户名和密码时,扫描会在 43,001 处停止并让您登录。如果您的凭据不正确,则会扫描所有 1,000,000 条记录。双核服务器上的处理时间差异可能以毫秒为单位。在具有 5 个用户帐户的 Windows Vista 上,这将在纳秒内完成。

【讨论】:

我想你会发现这里 99% 的发帖者都是不同层次的开发者。不要听起来那么自大。 我用的是 Ubuntu,只有一个用户。但是,当我提交错误的密码时,我需要 3 秒才能得到回复。所以,你错了:)【参考方案11】:

我同意。这是一个任意的编程决定。将延迟设置为一秒而不是三秒并不会真正损害密码的可破解性,而是使其更加用户友好。

【讨论】:

【参考方案12】:

从技术上讲,这种故意延迟是为了防止类似“线性化攻击” 的攻击(还有其他攻击和原因)

为了说明攻击,考虑一个程序(没有这个 故意延迟),它检查输入的序列,看它是否 匹配正确的序列,在这种情况下恰好是 “xyba。为了效率,程序员决定检查一个 一次一个字符,一旦出现不正确的字符就退出 找到了,在开始之前还要检查长度。

正确的序列长度比错误的序列长度需要更长的处理时间。更好(对于攻击者),一个序列号 第一个字符正确的将比任何 第一个字符不正确。等待时间的连续步骤 是因为每次多了一个循环,比较要经过 正确输入。

因此,攻击者可以选择一个四字符的字符串,并且以x开头的字符串占用的时间最多。 (通过猜测) 然后攻击者可以将字符固定为 x 并改变第二个字符,在这种情况下他们会发现 y 占用的时间最长。 然后攻击者可以将前两个字符固定为 xy 并改变第三个字符,在这种情况下,他们会发现 b 最长。 然后攻击者可以将前三个字符固定为 xyb 并改变第四个字符,在这种情况下他们会发现 a 占据了 最长。

因此,攻击者可以一次恢复连续一个字符。

Linearization.java.

Linearization.docx, sample output

序列号为四个字符,每个字符有 128 可能的值。 那么有 1284 = 228 = 268,435,456 个可能的序列。如果攻击者必须随机猜测 完整的序列号,她会在大约 227 = 134,217,728 次尝试,这是一项巨大的工作。另一方面,通过使用上面的线性化攻击,一个 每个字母平均只需要 128/2 = 64 次猜测,对于 预计的总工作量约为 4 * 64 = 28 = 256 次猜测, 这是一项微不足道的工作。

大部分书面武术改编自 this(摘自 Mark Stamp 的“信息安全:原则与实践”)。此外,上述计算并未考虑计算出正确序列长度所需的猜测量。

【讨论】:

以上是关于为啥检查错误的密码比检查正确的密码要花更长的时间?的主要内容,如果未能解决你的问题,请参考以下文章

为啥偶数 N 比奇数 N 花费更长的时间?

为啥 c 中的幂函数需要比预期更长的时间

为啥我使用 openMP atomic 的并行代码比串行代码花费更长的时间?

为啥通过 ASP.NET 方法运行查询比原生 SQL 需要更长的时间?

为啥一个循环比另一个循环检测共享内存更新需要更长的时间?

为啥我使用 modin.pandas 比使用 Pandas 需要更长的时间 [ray]