双因素认证

作者:Corey Steele

双因素认证旨在解决数十年来基于密码的攻击问题,例如暴力破解攻击和键盘记录攻击。在 Linux 中,双因素认证可以使用 pam_usb 实现,这是一个 PAM 模块,它提供了一种方法,让您可以针对存储在可移动媒体(如 USB 驱动器)上的加密令牌进行身份验证。通过 PAM 模块链的强大功能,本文将引导您完成双因素认证的配置。

PAM 是可插拔身份验证模块的缩写。根据 Linux-PAM 首页

PAM 提供了一种开发独立于身份验证方案的程序的方法。这些程序需要在运行时附加身份验证模块才能工作。要附加哪个身份验证模块取决于本地系统设置,并由本地系统管理员自行决定。

pam_usb 是由 Andrea Luzzardi 编写的 PAM 模块,它有助于从可移动媒体(如 USB 设备)进行身份验证,基于存储在驱动器和系统本身的强大加密密钥对。pam_usb 以源代码形式或二进制软件包形式提供,适用于各种发行版,包括 Debian、Gentoo、Fedora、Mandrake 和 SUSE。pam_usb 非常适合用于实现双因素认证,尽管它也可以用作唯一的身份验证模块。

术语“双因素认证”指的是使用两个独立且不同的标准来验证用户身份的身份验证:通常这是用户知道的东西和用户拥有的东西。在我们构建的配置中,用户知道的东西是用户名和密码对,而用户拥有的东西是我们将要生成并存储在 USB 驱动器上的强大加密令牌。

严格来说,您应该能够在任何版本的 Linux 上完成此处讨论的所有操作,只要该 Linux 版本具有可用的 PAM 配置和 2.4 或更高版本的内核,并且系统具有受支持的 USB 控制器。您还需要受支持的 USB 驱动器、pam_usb 模块源代码和一个 C 编译器。

我使用 Lexar 128MB Impact USB 1.1 驱动器在配备 Intel 82820 Camino USB 控制器的 IBM NetVista 上完成了此处讨论的所有操作。它运行的是 Debian 3.0 stable,使用 stock bf 内核 (2.4) 和 gcc-2.3。

您可以通过连接 USB 驱动器并运行以下命令来检查您的控制器和 USB 驱动器是否受支持lsusb以 root 用户身份运行。如果您的控制器和驱动器受支持,您应该在以下命令的输出中看到列出的驱动器lsusb。如果不是,请不要绝望;您的发行版可能没有自动加载必要的模块。请参阅《USB 指南》(请参阅在线资源)以获取有关设置 USB 环境的帮助。您可以通过运行以下命令检查您的登录程序是否链接到 libpam 来确认您的 PAM 安装ldd /bin/login | grep -i pam并检查输出。如果 login 链接到 libpam,则您的 PAM 配置应已设置。

pam_usb 模块的源代码可以从项目站点下载(请参阅资源)。使用任何浏览器导航到该网站并下载最新的源代码 tarball。记住您保存下载的位置。下载完成后,使用以下命令解压缩 tarballtar -zxvf pam_usb-X.Y.Z.tar.gz,其中 X、Y 和 Z 分别是您下载的 pam_usb 特定版本的主版本号、次版本号和构建版本号。现在您应该有一个 pam_usb-X.Y.Z 目录,所以cd进入该目录并快速查看以确保该目录中有一些文件。

pam_usb 没有configure 脚本,只有一个 Makefile,因此构建只需运行make从 pam_usb-X.Y.Z 目录中。如果您遇到错误(就像我一样),您可能缺少库。在我的 Debian 3.0 stable 系统上,我缺少 libncurses5、libpam0g 和 libreadline4 的开发包。安装缺少的库后,make 完成时没有错误。在 pam_usb 构建完成后,您可以使用以下命令安装它make install以 root 用户身份从 pam_usb-X.Y.Z 目录中运行。

安装完成后,是时候配置 pam_usb 了。配置 pam_usb 是一项相对简单的任务,可以分为三个主要步骤:创建 pam_usb 日志文件、备份您现有的 PAM 配置以及安装新配置。

创建 pam_usb 日志文件就是选择将其放在哪里以及命名为什么,以及创建文件。我个人的偏好是将所有日志保存在 /var/log 中,所以这就是我设置 pam_usb 日志文件的位置,也是本文中使用的位置。使用以下命令创建日志文件touch /var/log/pam_usb.log以 root 用户身份运行。接下来,将 /var/log/pam_usb.log 文件的所有权设置为与 /var/log 中其他文件的所有权匹配,如下所示

chown $USER:$GROUP /var/log/pam_usb.log

其中 $USER 和 $GROUP 是拥有 /var/log 中其他文件的用户和组。创建文件并设置所有权后,只需使用以下命令更改文件权限以反映 /var/log 中其他文件的权限

chmod 0600 /var/log/pam_usb.log

更高级的用户可能希望为 pam_usb.log 配置日志轮换计划,甚至使用以下命令将文件更改为仅追加chattr。这些选项留给读者自行探索。

现在日志文件已设置好,我们需要备份现有的 PAM 配置文件。这是一个重要的步骤,所以不要跳过它。在大多数系统中,PAM 配置文件存储在 /etc/pam.d 中。以 root 用户身份,使用以下命令创建备份副本

cp -rfp /etc/pam.d ~/pam.d/

为了测试,我们正在使用 su 的 PAM 配置,因为它是最容易测试的 PAM 感知应用程序。作为预防措施,您应该保持 root shell 打开并可访问,以便如果在配置 pam_usb 时出错,您可以通过使用 ~/pam.d 中的备份覆盖已编辑的配置文件来挽救自己。您还需要知道您将要配置的 USB 驱动器上使用的文件系统。在理想情况下,我们可以使用 mount 来完成这项工作,前提是 /mnt/usb 存在并且您的 USB 驱动器位于 /dev/sda 上。使用

mount /dev/sda1 /mnt/usb

然后运行

mount | grep usb

以查看驱动器上的文件系统是什么——文件系统在行尾的括号中列出。大多数 USB 驱动器使用 vfat 文件系统,并且只有一个分区。因此,它们可以使用以下命令挂载

mount -t vfat /dev/sda1 /mnt/usb

我们配置 pam_usb 的第一个真正步骤是修改 PAM 感知应用程序的 PAM 配置文件——对于您想要使用 pam_usb 进行身份验证的每个应用程序,此步骤都是必需的。因为我们出于测试目的正在使用 su,所以只关注 /etc/pam.d/su 文件。不要尝试在对 /etc/pam.d 目录进行单次批量编辑中配置每个 PAM 感知应用程序,否则您肯定会遇到麻烦。/etc/pam.d/ 中的文件对应于它们配置的应用程序,因此如果要配置控制台登录或 GNOME Display Manager 登录,您将分别关注 /etc/pam.d/login 和 /etc/pam.d/gdm。PAM 配置文件的命名模式应该是相对不言自明的。因此,在您最喜欢的文本编辑器中打开 /etc/pam.d/su,并在 pam_unix 行上方添加以下行

auth required pam_usb.so fs=vfat check_device=-1 \
  check_if_mounted=-1 force_device=/dev/sda \
  log_file=/var/log/pam_usb.log

如果您没有在 pam_unix 行之前包含上述行,则 PAM 永远不会达到针对 USB 设备进行身份验证的点。相反,它对通过 pam_unix 进行的身份验证感到满意,并退出了身份验证过程。

pam_usb 配置中的一些选项需要进一步解释:force_device 选项、pam_usb 模式、设备的文件系统以及我们将要使用的日志文件。

pam_usb 能够自动检测哪个 USB 连接的设备包含身份验证密钥。通过不指定 force_device 指令,pam_usb 会遍历所有连接的设备,并查找与指定用户名匹配的密钥。如果机器有多个 USB 设备,这些设备根据连接顺序分配设备名称——第一个设备是 /dev/sda,第二个是 sdb,依此类推,这将很有帮助。如果您指定 force_device 指令,除非您的 USB 驱动器被分配了 PAM 配置中指定的设备名称,否则您将无法进行身份验证。

pam_usb 支持三种操作模式:unique、alternative 和 additional。在 unique 模式下,您可以使用 USB 驱动器登录,但如果驱动器不存在,则无法登录。这可以通过注释掉 $PAMDIR/login 中的 pam_unix 并在上面添加配置行来实现。alternative 模式允许您只需插入 USB 密钥即可登录。如果密钥不存在,系统会提示输入密码。这可以通过保持 pam_unix 不变,在 PAM 配置文件中 pam_unix 条目上方添加上述配置行,并更改auth required行的位为auth sufficient。要实现真正的双因素认证,您需要同时要求用户名/密码对和 USB 密钥,这就是上述配置的设置方式。

Andrea Luzzardi 还指出了一种替代的双因素认证方法,该方法涉及加密存储在 USB 驱动器上的私钥,之后密钥需要密码才能解密并用于身份验证。pam_usb 能够将提供给 PAM 的密码传递下去,以解密私钥,从而通过单个用户名和密码对实现双因素认证。此外,这在不损害双因素认证的任何安全优势的情况下完成。这种身份验证方法取决于为用户帐户使用与用于加密 pam_usb 使用的私钥相同的密码。要加密 pam_usb 使用的私钥,只需使用 usbadm 工具创建加密令牌

usbadm cipher /path/to/usb/filesystem \
username algorithm

,其中选项已根据 usbadm man page 中的 cipher 指定。

fs= 选项告诉 pam_usb 要尝试使用哪个文件系统来挂载和读取 USB 驱动器。如果您的用户在其 USB 驱动器上有不同的文件系统,您将遇到麻烦。只需指定您的 USB 驱动器上使用的任何文件系统即可。

在您对 su 的 PAM 配置进行配置更改后,是时候为使用系统的每个用户设置加密密钥对了。最初,这只需使用以下命令即可完成

usbadm keygen /path/to/mounted/usb/drive keysize

,其中 keysize 是您要生成的密钥的大小(以位为单位),/path/to/mounted/usb/drive 是——您猜对了——您挂载的 USB 驱动器的根路径。对于我的设置,我选择了 4,096 位的密钥大小,这应该足以防止对您的密钥对进行甚至坚决的暴力破解尝试。RSA Labs 建议 DSA 密钥不应小于 2,048 位,因此至少使用 2,048 位的密钥大小。usbadm 程序在您的 USB 驱动器的根目录中生成名为 .auth/$USER.$HOST 的文件,其中 $USER 是执行 usbadm 命令的用户名,$HOST 是生成密钥的机器的主机名。必须存在 ~$USER/.auth 中的相应密钥集才能使用 USB 令牌进行身份验证。

如果 USB 驱动器丢失(这种情况不可避免地会发生),您可以删除用户的 ~/.auth/id_pub 文件,并按照上述说明重新生成密钥对。请务必不要丢失 root 的私钥,否则您将不得不启动到安全介质,禁用双因素认证,并再次完成整个设置过程以恢复功能。

在您新生成密钥对后,您现在可以准备好使用 su 测试 pam_usb 和双因素认证。插入您的 USB 驱动器并尝试su切换到具有有效密钥对的用户;最好从非 root 帐户进行测试。您应该像以前一样被提示输入用户名,但现在不会立即提示您输入密码,而是会看到 USB 错误,因为 pam_usb 尝试挂载 /dev/sda,或者您告诉它尝试的任何基本设备。如果 pam_usb 能够找到您的 USB 驱动器,您应该会被提示输入用户密码,如果输入正确,应该会为该用户帐户生成一个 shell。您可以通过检查 pam_usb 日志文件并验证最后一行附近是否有一行内容为Access granted。如果您在 pam_usb.log 文件中看到该行,那么恭喜您——su 现在已配置为使用双因素认证。

一旦您对 su 的 pam_usb 功能感到满意,您就可以将 su 的配置复制到您想要使用双因素认证设置的其他应用程序。请务必向所有用户颁发必要的密钥,并在您注销系统和/或重新启动之前彻底测试。

与任何身份验证系统一样,双因素认证并非没有弱点。这种特定实现容易受到私钥盗窃的影响,因为很容易复制 USB 驱动器的内容。在 2005 年 3 月 15 日的 Crypto-Gram 中,Bruce Schneier 撰写了一篇颇具批判性的文章,详细说明了为什么双因素认证并非身份验证的终极解决方案——他的观点的症结在于,人们正在使用双因素认证来实现它原本不打算实现的目标。考虑到这一点,请记住双因素认证旨在解决基于密码的攻击这一古老问题。pam_usb 非常好地实现了这一目标,如果配置正确,它可以有效地提高给定工作站的安全性。

本文资源: /article/8528

Corey Steele 是一位拥有六年经验的安全专家;他于 2004 年获得 CISSP 认证。他在安全领域的主要兴趣是访问控制和网络安全。他在金融领域为一家制造核心银行软件的公司工作。自 1995 年以来,他一直是自由/开源软件社区的积极成员,并为各种项目做出了贡献。在业余时间,他喜欢编写代码并就安全主题发表演讲。

加载 Disqus 评论