为什么密码不正确时`sudo`很慢?

发布于 2025-01-02 13:07:11 字数 318 浏览 1 评论 0原文

当我输入超级用户权限的密码或登录 Linux 机器时,如果输入正确,它会立即返回,授予我访问权限。但是,如果我输入错误,则需要等待很长时间才能告诉我密码不正确。通常,我会比计算机早意识到自己搞砸了。

为什么会这样呢?据我了解,用户密码被加密并存储在 /etc/shadow 中,所以看起来我的输入应该被加密并与我的用户名文件中的内容进行比较——这将无论我是否输入正确的密码,花费的时间都大致相同。是否有一些算法原因,比如它必须检查一堆额外的地方才能确认它是不正确的?或者系统可能很快就知道这是一个不正确的密码,但必须做大量工作来跟踪不正确的登录尝试。或者也许它只是想惩罚我搞砸了。

When I enter my password for superuser privileges or to log in to my Linux box, if I enter it correctly, it returns immediately, granting me access. However, if I make some typo, there is a long wait before it tells me my password is incorrect. Usually, I realize that I messed up long before the computer does.

Why is this the case? As I understand it, user passwords are encrypted and stored in /etc/shadow, so it seems like my input should just be encrypted and compared to what is in that file for my username---which would take roughly the same time whether I enter the correct password or not. Is there some algorithmic reason, like it has to check in a bunch of extra places before it can confirm that it is incorrect? Or maybe the system knows it's an incorrect password quickly, but has to do a lot of work to keep track of incorrect login attempts. Or maybe it's just trying to punish me for screwing up.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

优雅的叶子 2025-01-09 13:07:11

这完全是故意的:这样做的原因是为了让使用字典攻击来猜测密码变得不可能。

快速周转对于字典攻击至关重要。减慢错误密码的速度是一种减缓攻击速度的方法,使其无法在有意义的时间间隔内执行。

This is done totally on purpose: the reason for that is to make it impossible to guess a password using a dictionary attack.

Fast turn-around is crucial for a dictionary attack. Slowing down on incorrect passwords is a way to slow the attack to a crawl, making it impossible to execute in a meaningful time interval.

三岁铭 2025-01-09 13:07:11

好吧,我做了一些研究,结果发现……没有理由!

我相信 sudo 的工作原理是:

  1. 它加载 libpam.so 。 libpam.so 只是一个普通的库。没有特殊权限。
  2. 它询问libpam,“当前用户的密码是否正确?”。
  3. 如果 libpam 说“是”,那么它将以 root 身份运行该命令(sudo 是 SUID,因此它可以执行此操作)。

延迟由libpam插入。延迟的计算方式实际上超级超级复杂——甚至是稍微随机的。有些代码已经有 25 年历史了,所以有点难以理解。我认为延迟是在 pam_authenticate() 中触发的,其中有以下代码:

_pam_await_timer(pamh, retval);   /* if unsuccessful then wait now */

并且实际延迟以某种方式通过调用 pam_fail_delay()。该页面有一些有用的信息,包括基本原理:

通常可以通过利用身份验证方案拒绝申请用户访问所需的时间来攻击该方案。在短超时的情况下,尝试暴力字典攻击可能被证明是可能的——通过自动化过程,攻击者尝试所有可能的密码来访问系统。在其他情况下,个别故障可能需要相当长的时间(表明故障的性质),攻击者可以获得有关身份验证过程的有用信息。后者的攻击利用了程序延迟,从而构成了有用信息的隐蔽通道。

在我的 RHEL 8 系统上,延迟是使用 失败延迟 PAM 插件 设置的。如果您编辑 /etc/pam.d/system-auth 那么您会看到这一行:

auth        required                                     pam_faildelay.so delay=2000000

将其注释掉,延迟就会消失!根据文档,这是本地身份验证的常见配置,并且有还有用于远程身份验证的password-auth,因此消除此延迟应该100% 安全

一些陷入困境的人可能会尖叫但是本地字典攻击!!1!现在就在我身上。不要听他们的尖叫声。

回想一下我所说的 libpam.so 是一个普通的库。它不是 SUID,那么它如何实际检查您的密码(因为 /etc/shadow 现在已经不能只看到哈希值了)。答案是它调用一个辅助二进制文件IS SUID。它称为 unix_chckpwd,它可能位于您的 PATH 上。如果你运行它,它会检查 stdin 是否是 TTY,并执行一些愚蠢的安全操作:

❯ unix_chkpwd 
This binary is not designed for running in this way
-- the system administrator has been informed

最后等待 10 秒,实际上没有任何原因,只是为了惹恼你。我不是在开玩笑:

sleep(10);  /* this should discourage/annoy the user */

无论如何,现在可能让您烦恼的一个想法是“如果 PAM 造成延迟并且它只是一个普通的非 SUID 库,那么它如何安全地存储访问尝试时间,例如做指数延误?”

嗯……事实并非如此。不想等待 sudo 的延迟?您只需运行 sudo 的新实例即可。但你甚至不需要它,因为 unix_chkpwd 有这样的评论:

    /*
     * we establish that this program is running with non-tty stdin.
     * this is to discourage casual use. It does *NOT* prevent an
     * intruder from repeatedly running this program to determine the
     * password of the current user (brute force attack, but one for
     * which the attacker must already have gained access to the user's
     * account).
     */

延迟是 100% 安全剧院。它对阻止本地字典攻击没有任何作用。

我的意思是,即使确实如此,如果您有权访问本地用户的帐户,那么在不破解密码的情况下获取他们的密码也是微不足道的。

那么我们学到了什么?

  1. sudo 的延迟没有任何意义。
  2. PAM 的安全架构非常疯狂。
  3. PAM 本身是无状态的,因此它实际上无法实现指数延迟。我的 PAM 客户端(例如 sshd)可以。

那么最后,如果这种延迟完全没有意义,为什么还要存在呢?我的猜测是a)它让人们感到安全(看看这个问题中的所有回复都说它提高了安全性),b)它对于基于密码的远程身份验证确实有意义,所以我猜他们为此添加了该功能,然后没人愿意为 sudo 关闭它吗?

Ok I did some research and it turns it... there is no reason!

I believe how sudo works is:

  1. It loads libpam.so. libpam.so is just an ordinary library. No special permissions.
  2. It asks libpam, "is the password for the current user correct?".
  3. If libpam says "yes" then it runs the command as root (sudo is SUID so it can do that).

The delay is inserted by libpam. It's actually super super complicated how the delay is calculated - it's even randomised slightly. Some of the code is 25 years old so it's a bit hard to follow. I think the delay is triggered in pam_authenticate() where there's this code:

_pam_await_timer(pamh, retval);   /* if unsuccessful then wait now */

And the actual delay is somehow set by calls to pam_fail_delay(). That page has some helpful information including rationale:

It is often possible to attack an authentication scheme by exploiting the time it takes the scheme to deny access to an applicant user. In cases of short timeouts, it may prove possible to attempt a brute force dictionary attack -- with an automated process, the attacker tries all possible passwords to gain access to the system. In other cases, where individual failures can take measurable amounts of time (indicating the nature of the failure), an attacker can obtain useful information about the authentication process. These latter attacks make use of procedural delays that constitute a covert channel of useful information.

On my RHEL 8 system the delay is set using the fail delay PAM plugin. If you edit /etc/pam.d/system-auth then you see this line:

auth        required                                     pam_faildelay.so delay=2000000

Comment it out and the delays disappear! According to the docs this is a common config for local authentication and there's also password-auth for remote auth, so it should be 100% safe to remove this delay.

Some stuck-in-the-muds are probably screaming BuT lOcAl DiCtIoNaRy AtTaCkS!!1! at me right now. Don't listen to their squeals.

Recall how I said libpam.so is an ordinary library. It isn't SUID, so how does it actually check your password (since /etc/shadow is a thing now it can't just see the hash). The answer is it calls a helper binary that IS SUID. That is called unix_chckpwd, and it's probably on your PATH. If you run it it checks if stdin is a TTY and does some silly security theatre:

❯ unix_chkpwd 
This binary is not designed for running in this way
-- the system administrator has been informed

There's a 10 second wait at the end for literally no reason but to annoy you. I'm not joking:

sleep(10);  /* this should discourage/annoy the user */

Anyway, a thought that might be niggling at you now is "so if PAM is responsible for the delay and it's just a normal non-SUID library, how does it securely store access attempt times, and e.g. do exponential delays?"

Well... it doesn't. Don't want to wait for sudo's delay? You can just run a new instance of sudo. But you don't even need that because unix_chkpwd has this comment:

    /*
     * we establish that this program is running with non-tty stdin.
     * this is to discourage casual use. It does *NOT* prevent an
     * intruder from repeatedly running this program to determine the
     * password of the current user (brute force attack, but one for
     * which the attacker must already have gained access to the user's
     * account).
     */

The delay is 100% security theatre. It does nothing to stop local dictionary attacks.

I mean even if it did, if you have access to a local user's account it's trivial to get their password without cracking it.

So what have we learned?

  1. There's no point to sudo's delay.
  2. The security architecture of PAM is crazy.
  3. PAM itself is stateless so it actually can't do exponential delays. I client of PAM (e.g. sshd) could though.

So finally, why does this delay exist if it is totally pointless? My guess is a) it make people feel secure (look at all the replies in this question saying it improves security), and b) it does make sense for remote password-based authentication, so I guess they added the feature for that and then nobody bothered to turn it off for sudo?

划一舟意中人 2025-01-09 13:07:11

我不确定这个问题是否与此相关。我也不确定我的答案的正确性,但我认为这是为了安全。让它慢n倍意味着暴力攻击将花费n倍的时间。

I am not sure if this question is relevant here.. I am also not sure of the correctness of my answer but I think it's for security. Making it n times slower would mean that a bruteforce attack would take n times longer.

无敌元气妹 2025-01-09 13:07:11

当您输入错误密码时,sudo 的响应速度很慢,因此,如果您使用 sudo 发起粗暴的“尝试猜测密码”攻击,您的速度就会变慢每次猜错时都会下降,这样攻击的时间就会更长。那些合法使用它的人没有理由抱怨。如果你偶尔犯一个错字,你不会介意的。如果您确实无法输入自己的密码,则可能需要将其更改为您可以输入的密码(安全)。

The slow response from sudo when you enter an erroneous password is so that if you are mounting a crude brute force 'try and guess the password' attack with sudo, you are slowed down every time you guess wrong, so that the attack takes longer. Those who are using it legitimately have no cause for complaint. If you make a typo every once in a while, you won't mind. If you really can't type your own password, it might be time to change it to something (secure) that you can type.

花开半夏魅人心 2025-01-09 13:07:11

控制台或 SSH 登录也很慢。任何需要密码的操作都会被“放慢”以阻止暴力攻击。

Console or SSH Login is slow too. Anything that requires a password is "slowed-down" to stop brute-force attacks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文