第十三章:身份验证

Sudo的身份验证系统看起来非常简单:输入密码并运行特权命令。但是sudo会让你改变它处理密码的方式,你必须多久输入一次密码,以及是否需要密码。你可以告诉sudo要求比密码更强的身份验证,比如要求SSH代理或硬件令牌或我从未听说过的其他身份验证方法,以及它如何处理身份验证方法。

我们将从最简单的情况开始,密码管理。

Sudo 密码设置

您可以控制sudo请求密码的方式,sudo允许用户尝试输入密码的次数,以及sudo如何在终端会话之间共享身份验证。

密码尝试和超时

Sudo为用户提供了三次输入密码的机会。也许你的用户在第一次、第二次或第三次尝试时无法成功键入密码。使用 password_tries 选项给他们一些额外的尝试。

Sudo给用户五分钟的时间输入密码,然后超时。我觉得这太过分了。如果用户无法在60秒内键入密码,我不希望他们在我的服务器上。可悲的是,Thea 比我更宽容。使用passwd_timeout 选项设置超时时间(分钟):

用户有五次尝试输入密码,但密码提示在两分钟后超时。

当用户输入密码时,Sudo通常不会给出任何反馈。如果你想让用户在输入时看到一些东西,请使用 pwfeedback 选项:

大多数安全人员不鼓励使用 pwfeedback 选项。任何观察用户类型的人都会知道用户密码的长度。

目标密码

sudo的一个特点是,它要求用户的密码来执行特权操作,而不是root密码。根据我的经验,在某些环境中,系统所有者可能希望用户输入目标用户的密码,而不是他们自己的密码——通常是出于审计合规的原因。为此,请使用 rootpwtargetpwrunaspw 选项。

rootpw 选项告诉sudo需要root密码,而不是用户的密码。下面示例中,wheel组中的用户必须使用sudo的root密码。

targetpw 选项告诉sudo需要目标用户的密码,而不是用户的密码。如果用户使用 -u 命令行参数以其他用户的身份运行命令,则需要输入该用户的密码:

最后,runaspw 选项告诉sudo需要默认RunAs用户的密码,而不是用户的密码。您可能希望运行Oracle目录中任何程序的用户使用Oracle帐户的密码,而不是自己的密码:

在所有这些之间,您可以根据需要自定义必要的密码。然而,你确实有可能让用户感到困惑。如果有办法告诉用户他们需要输入哪个密码就好了…

自定义密码提示

Sudo的密码提示有点无聊。密码:可以完成这项工作,但passprompt选项可以让你做更有趣的事情。

这充其量只是有点好笑。但是在密码提示字符串中使用转义符使自定义提示很有用。

要在密码提示中使用计算机的主机名,请使用 %H%h%h 是短主机名,而 %H 是完全限定主机名。只有当设置了fqdn选项或hostname命令返回完全限定的主机名时,Sudo才能获得完全限定主机名:

要命名sudo需要密码的用户,请使用 %p 。这会提醒用户在使用 rootpwrunaspwtargetpw 选项时输入什么密码:

要指定运行命令的用户,请使用 %U 。如果您的用户经常以root以外的用户身份运行命令,这可以帮助他们保持正常。哎呀,这有助于我把事情弄清楚:

要命名运行sudo的用户,请使用 %u 。如果您有多个用户帐户,这也可能有助于您保持正确:

如果您需要在提示中使用百分号,请使用两个连续的百分号(%%)。

passprompt 选项要求系统的身份验证系统(PAM或类似系统)使用密码提示Password:。如果您的系统使用其他东西作为密码提示,请使用选项 passprompt_override 停止该检查,并坚持让sudo使用您的自定义提示。

身份验证缓存和超时

Sudo不会缓存您的密码或其他身份验证凭据。但是,它确实会记住您上次在给定的终端会话中成功通过身份验证的日期和时间。这使您可以在接下来的几分钟内再次运行sudo,而无需使用密码。您可以控制sudo如何处理此缓存,以及sudo在不重新输入密码的情况下为您运行命令的时间。如果您以root身份运行 sudo -V 并搜索字符串 timestamp ,您将看到sudo的身份验证计时设置:

一旦您输入了密码,您将不需要在该终端窗口中再次输入五分钟。使用 timestamp_timeout 选项和超时分钟数更改此设置。使用0禁用时间戳:

如果使用负值,时间戳将永远不会过期。不要那样做。

根据 sudo –V ,时间戳位于 /var/db/sudo 目录中。使用 timestamp_dir 选项更改目录。虽然root通常拥有目录和其中的时间戳,但您可以使用 timestamp_owner 选项进行更改。我强烈建议您将这些设置保留为操作系统默认值,除非您的操作系统供应商或sudo开发人员告诉您更改它们。

用户更新身份验证超时

用户可以通过更新上次身份验证的时间或删除缓存的凭据来与身份验证缓存进行交互。

如果你想在不运行任何命令的情况下对sudo进行身份验证,请运行 sudo –v 。Sudo将提示您输入密码,验证密码并更新时间戳。当您要通过sudo运行一大堆命令,并且不想中途被密码提示阻止时,请使用此选项。

如果您希望sudo忽略此终端窗口的身份验证时间戳缓存,请使用–k选项。单独使用时,它会使身份验证时间戳无效。如果您特别希望sudo在下次运行命令时请求身份验证,请在命令行中添加 -k

即使您的身份验证时间戳还有时间,sudo现在也会要求您进行身份验证。

要从所有sudo会话中完全删除身份验证时间戳,请运行 sudo –K 。这将完全删除您的时间戳,或者如果无法删除,则将其重置为1969年12月31日。在离开电脑之前使用 sudo –K ,即使你运行了屏幕锁定程序。记住,系统管理员可以克服大多数屏幕锁。你不希望像我这样的白痴解锁你的工作站并使用你的sudo访问权限。

禁用身份验证

有时,您希望用户能够在不输入密码的情况下运行命令。如果您总是重新配置笔记本电脑以连接到不同的网络,那么不必为 dhclientifconfig 和相关命令设置密码可能是有意义的。您甚至可能希望在桌面上始终运行 sudo 而无需密码。对于自动化任务来说,在没有密码的情况下运行sudo是非常合理的。

广泛禁用sudo身份验证是不明智的。是的,这是最方便的。此外,任何获得用户会话控制权的应用程序都可以完全访问您的所有sudo权限。如果你运行的是像Ubuntu这样的操作系统,它通过sudo为初始用户提供完全的root访问权限,那么流氓进程将完全拥有你的机器。禁用sudo身份验证相当于故意实施Windows 95安全系统。如果您不想在需要sudo时费心输入密码,请查看另一种身份验证机制,如SSH代理(请参阅本章后面的sudo和PAM)。

我的示例假设您有选择地禁用身份验证。您可以推断它们全局禁用身份验证,或查看大多数操作系统附带的默认sudoers文件。

身份验证选项

控制身份验证的一种方法是Defaults语句上的 authenticate 选项。 authenticate 选项不会出现在大多数sudoers文件中,因为它是一个不可见的全局默认值。否定它以禁用身份验证。这里我禁用 ifconfigdhclient 的身份验证:

我现在可以在咖啡店设置我的笔记本电脑,而无需担心密码。

身份验证标签

如果您想非常精确地控制sudoers策略中的身份验证,请在特定的sudoers规则上使用标签 PASSWDNOPASSWD 。您很少看到PASSWD标签,因为它是默认标签。使用NOPASSWD关闭密码要求。

Pete可以使用sudo在主机dbtest1上以用户oracle的身份运行任何Oracle命令,而无需输入密码。

在会话之间共享身份验证

Sudo通常在认证时间戳中包含终端设备。也就是说,sudo不仅使用用户名,还使用终端设备(或TTY)来识别用户会话的sudo身份验证。

假设我两次通过SSH连接到服务器,我的会话使用虚拟终端 /dev/vty2/dev/vty3 。如果我在 vty2 终端窗口中使用sudo,并想在 vty3 窗口中再次使用它,我必须在 vty3 窗口中进行身份验证。

一些操作系统包括一个sudo包,配置为允许在终端会话之间共享sudo身份验证。如果您向服务器打开两个SSH会话,并在一个会话中通过sudo进行身份验证,则另一个会话可以使用相同的身份验证时间戳。

这对许多人来说似乎很奇怪——我当然觉得很奇怪。但是,当这两个进程都由同一用户拥有时,很难将它们相互隔离。毕竟,用户可以完全控制自己的进程。这意味着,如果一个熟练的入侵者在用户在另一个会话中处于活动状态时渗透了用户帐户,只要任何终端会话都有有效的时间戳,入侵者就可以使用ptrace和gdb等工具通过sudo运行命令。尽管如此,要求对每个终端窗口进行单独的身份验证确实增加了攻击者进一步渗透系统所需的技能——你的普通脚本小子不具备劫持另一个终端的sudo会话所需的专业知识。

您可以使用 ttytickets 选项控制每个终端的身份验证。否定此选项可以让多个终端共享一个时间戳进行身份验证。但是,除非您有非常具体的原因禁用每个终端的时间戳,否则我强烈建议您保持启用状态。

查询Sudo

Sudo有两个不运行命令的用户函数。–l 标志告诉sudo打印出用户的sudo策略,这样用户就可以看到他们可以访问的内容。–v 标志更新用户的身份验证超时。用户必须输入密码才能使用这些功能,但您可以更改这些功能,使其仅在某些情况下需要密码。

listpw 选项控制用户是否必须输入密码才能列出其访问权限,而 verifypw 选项控制用户能否输入密码以更新其身份验证时间戳。这些选项中的每一个都可以有四个值之一:anyalwaysallnever

默认值 any 表示,如果用户的任何sudoers规则具有NOPASSWD或设置了 !authenticate ,则用户不需要输入密码即可使用该功能。关闭一个命令的密码身份验证意味着启用sudo的 -l-v 标志的无密码使用。

如果这些选项设置为 always,则用户每次要使用这些功能时都必须输入密码。即使用户的身份验证时间戳尚未过期,用户也必须始终输入密码才能使用 -l-valways 意味着“总是”。

如果将这些选项设置为 all-l-v 将请求密码,除非用户在此主机上对其所有允许的命令具有无密码访问权限。请注意,他们不需要对所有可能的命令进行无密码访问,只需要对他们可以运行的所有命令进行无口令访问。

never 设置意味着用户永远不会被要求输入密码来使用 -l-v

这里sudoers告诉 sudo –l 要求除了Thea之外的每个用户都有一个密码。我们还禁止请求密码来更新主机www上的身份验证时间戳。

更改命令或RunAs的 listpwverifypw 选项没有多大意义,但您可以为主机和用户明智地更改它们。

讲座

我在第5章的许多例子中都使用了sudo讲座,但让我们更集中地讨论一下。“讲座”是您首次通过sudo身份验证时显示的消息:

然后,您有机会输入密码。这是一个很好的一般警告,但讲座和 lecture_file 选项让你有机会根据情况需要进行更具体的讲座。

讲座选项接受三个值。默认情况下,一次,告诉sudo给每个用户讲一次,以后再也不讲了。使用 always 告诉sudo总是教导用户,而使用 never!lecture 使讲座完全无效。

使用 lecture_file 选项提供一个包含您自己的讲座的文件。您可以根据任何默认设置设置讲座。因此Thea可以设置以下配置:

mike-lecture 文件可能包含这样的内容:

显然有人认为我是个麻烦。

Sudo 和 PAM

密码不是很强的身份验证令牌。大多数用户创建的密码都很糟糕,一个足够持久的入侵者最终甚至可以猜出像样的密码。为您的特权进程添加另一层身份验证,或完全消除密码,可以提高您的安全性。

可插拔身份验证模块(Pluggable Authentication Modules —— PAM)允许系统管理员将新的身份验证系统连接到程序。每个身份验证系统都包含一个PAM模块,其中包含使用身份验证系统所需的代码。除了类Unix系统上常见的密码、Unix、Kerberos和LDAP模块外,您还可以安装实现Google身份验证、RSA令牌、Windows SMB身份验证等的PAM模块。并非所有操作系统都支持PAM,但如果您的操作系统支持PAM,您可以利用PAM对sudo进行身份验证。

正如这不是一本关于LDAP的书一样,这也不是一本有关PAM的书。本节可能包含足够的知识,可以让我的示例PAM模块在您的系统上使用sudo工作,但它不会让您成为PAM向导。不要忘记,许多供应商都有自己的PAM系统,而开源世界有两个类似但不完全相同的实现。如果您想要高级PAM配置,请查看操作系统的文档,了解您拥有什么以及它能做什么。

然而,许多PAM模块并不适合我的环境。使用谷歌身份验证器不仅会从我的网络中删除信任源,还意味着如果我的外部网络连接失败,我将无法进行身份验证。我不会对Windows域进行身份验证,也不会在此公司部署RSA令牌。然而,SSH代理身份验证模块很有趣。

SSH代理在用户的台式计算机上运行。它在内存中保存用户解密的SSH身份验证密钥。如果SSH客户端或会话需要验证密钥的持有,它会要求桌面代理执行验证。这比密码身份验证更强,因为用户必须同时拥有密钥和密钥的密码。当然,您不应该允许所有SSH服务器访问您的代理,但这很容易配置。如果这段话对你来说没有意义,请允许我推荐我的书《SSH Mastery》(倾斜风车出版社,2012)。

PAM模块 pam_ssh_agent_auth (http://pamsshagentauth.sourceforge.net/)允许进程对SSH代理进行身份验证。我将使用此模块作为向sudo添加安全系统的示例。

先决条件

在配置sudo使用SSH代理身份验证之前,请检查您是否具备所有先决条件。

您必须在本地计算机上拥有用户 authorized_keys 文件。这意味着,如果您使用的SSH服务器从LDAP或其他外部源获取密钥,则无法使用 pam_ssh_agent_auth

SSH客户端必须将桌面SSH代理转发到服务器,服务器必须接受代理转发。要查看这在SSH会话中是否有效,请检查环境变量SSH_AUTH_SOCK。

如果此变量包含路径,则您的代理转发工作正常,或者您遇到了一个非常奇怪的问题。如果此变量不存在,请检查SSH客户端和服务器设置。

现在安装 pam_ssh_agent_auth 。与许多现代软件不同,pam_ssh_agent_auth 没有各种花哨的配置选项。如果您的操作系统有打包版本(很可能确实如此),请使用它。

SSH代理身份验证需要环境变量SSH_AUTH_SOCK,SSH会自动将其设置为指向连接到SSH代理的本地套接字。您需要在sudoers策略中允许此环境变量。我还建议传递SSH_CLIENT、SSH_TTY和SSH_CONNECTION,以便sftp等程序能够工作。

Sudo默认在您进行身份验证时设置身份验证时间戳。在尝试部署新的身份验证系统时,这种行为会让你遇到问题。通过将 timestamp_timeout 选项设置为0来禁用时间戳:

一旦这些先决条件满足,您就可以继续配置PAM模块。

配置 PAM

PAM将身份验证配置保存在系统目录中,如 /etc/pam.d/usr/local/etc/pam.d 。PAM感知程序在这些目录中搜索其PAM。检查这些目录中是否有名为 sudo 的文件。

PAM策略包括四种不同类型的规则:auth, account, session, 和 password。更改身份验证方法需要更改身份验证规则。并非所有PAM策略都具有所有规则类型——许多策略没有密码规则。每个规则都调用一个PAM模块,如 pam_unix , pam_ldap , pam_mkhomedir 等。

PAM模块 pam_unix 处理传统的密码身份验证。在sudo的PAM配置中找到一个与此类似的身份验证规则:

此规则告诉sudo使用密码进行身份验证。要使用SSH代理身份验证而不是密码,请用您自己的密码规则替换密码规则。

这是什么意思?使用共享库 pam_ssh_agent_auth.so 中的方法进行身份验证就足以登录到系统。file= text给出了用户的 authorized_keys 文件的路径,该文件通常位于 $HOME/.ssh/authorized_key 中。您可能需要提供 pam_ssh_agent_auth.so 的完整路径,具体取决于您的操作系统如何安装新的PAM库以及PAM实现如何找到它们。

保存对sudo PAM策略的更改。现在,您应该能够通过SSH代理向sudo进行身份验证。刷新您的身份验证时间戳(如果有的话)并尝试。

虽然我的PAM规则适用于最常见的情况,但服务器可以通过多种方式存储其 authorized_keys 文件。pam_ssh_agent_auth 库必须知道密钥的位置以及密钥文件的可接受权限。

authorized_keys权限

在最简单的情况下,用户拥有自己的 authorized_keys 文件。然而,有些环境不允许用户更改自己的 authorized_key 。相反,密钥文件更新通过一个中央管理系统,该系统将它们复制到目标主机。在这种环境中,受感染的用户无法更改服务器上的密钥文件。问题变成了:谁拥有关键文件?

allow_user_owned_authorized_keys_file 选项告诉pam_ssh_agent_auth用户可以拥有 authorized_keys 文件。当密钥文件位于用户的主目录中时,此选项会自动激活。

如果不设置此选项,并且 authorized_keys 文件不在用户的主目录中,pam_ssh_agent_auth 希望root拥有密钥文件。如果文件不归root所有,则身份验证失败。

authorized_keys位置

虽然大多数教程都告诉您将 authorized_keys 放在用户的 $HOME/.ssh 目录中,但许多组织使用其他标准。您必须告诉 pam_ssh_agent_auth在哪里可以找到文件。为此,该模块包括几个转义字符。

波浪号( ~ )和 %h字符表示用户的主目录。

%H 表示短主机名(不含域名),而 %f 表示完全限定主机名。

最后,%u 代表用户名。

假设您将密钥存储在 /etc/sshkeys/ 中,其中每个用户都有一个以其用户名命名的文件。这些密钥文件归root所有。

如果用户可以在此目录中写入自己的密钥文件,则必须在PAM规则末尾添加 allow_user_owned_authorized_keys_file 选项。

调试 pam_ssh_agent_auth

如果sudo提示您输入密码并等待您输入,则表示您没有删除密码策略。如果sudo连续三次提示您输入密码而没有等待您输入密码,然后显示失败消息,则sudo正在使用PAM模块,但无法连接到您的SSH代理。检查您的代理转发。如果仍然有问题,请在 sudo.conf 中配置日志记录,以查看问题所在。

一旦你让pam_ssh_agent_auth使用sudo,你就可以进一步扩展身份验证要求。您想要求SSH代理、密码和Google身份验证吗?你能做到的。这有点傻,但你能做到。

考虑到这一点,你现在可以让sudo做任何你想做的事情。

后记

现在,你应该比绝大多数没有写sudo的人更了解sudo。恭喜你!但还有更多的东西要学。如果你有一个奇怪的sudo问题,请查看sudo网站http://sudo.ws、sudo手册页和sudo用户邮件列表的存档。Sudo已成功部署在数百万种不同的系统上,它也可以为您工作。

但是,请始终注意sudo可能不适合您的组织。一些应用程序希望拥有服务器,试图限制这些应用程序充其量是徒劳的。如果您以root身份运行shell脚本来管理您的组织,那么使用sudo运行这些相同的shell脚本将为未经授权的用户提供许多升级权限的方法。Sudo是有用的,但了解特定工具何时无法解决问题的系统管理员更有用。

下一次当有人告诉你“苏多是你扎根的方法”时,请他们接受Slap仙女短暂而尖锐的拜访。