delphij's Chaos

选择chaos这个词是因为~~实在很难找到一个更合适的词来形容这儿了……

11 Oct 2011

配合sudo使用 Google Authenticator

Google Authenticator 是一个 TOTP(基于时间的一次性口令)实现,它采用了 RFC 4226 算法。

Google Authenticator 与 RSA SecurID 非常类似。具体来说,它使用一个随机串和以整数表达的时间作为输入去计算 HOTP(算法是 HMAC-SHA-1),然后取输出的最后几位作为一次性口令。

虽然目前已经发现了一些 SHA-1 的弱点,但目前为止还没有公开的已知算法可以从 hash 值直接高效地反推出明文信息。另一方面, HOTP 只截取 hash 的最后几位,因此,攻击者在知道可能的明文信息之后,还必须获得足够多的 TOTP 时间和 hash 值才能够进行离线验证。

在现代 Unix 系统上,通常使用 PAM 来完成系统的验证工作。在 FreeBSD 上,可以通过 security/pam_google_authenticator 来安装 Google Authenticator 的 PAM 模块。这样就可以配置 sudo 来使用它做验证了。

在 /usr/local/etc/pam.d/sudo 中,auth部分预设是这样的:

auth include system

这表示采用系统内建的 ‘system’ 规则配置。我们在这后面加入强制使用 Google Authenticator 的配置:

auth required /usr/local/lib/pam_google_authenticator.so noskewadj

这里的 required 表示如果验证失败则认为整个验证链失败。

如果不需要用户重新输入口令,则可以用上面这行换掉include那行。

在 sudoers 中还需要配置使用口令。如果是 NOPASSWD,则系统会绕过 auth 这一部分。

需要注意的是,由于 sudo 是一个特权提升点,因此假如用可以被用户自行改动的文件作为访问控制机制,便会构成一个显然的安全漏洞。因此,对应的 Google Authenticator 配置应以 sudo 的目标用户的身份进行(此外还应在sudoers中配置 Defaults rootpw):

sudo google-authenticator

也许应该抽时间改进一下,例如把 authenticator 的修改做成 setuid 的,并实现先验证之后再改?