21.20.4
5 /etc/passwd和/etc/shadow文件里的安全问题
口令管理不善是最常见的一种安全弱点。/etc/passwd和/etc/shadow这两个文件的内容决定了谁可以登录,以及一旦他们获准入内可以做什么。这个文件是系统抵抗闯入者的第一道防线这个文件是系统抵抗入侵者的第一道防线。必须小心翼翼地维护它,不能有错误、安全隐患和历史包袱。参考6.1节了解有关passwd文件的更多信息。
在老式系统上,/etc/passwd文件的第二个字段有一个表示用户加密口令的字符串。因为/etc/passwd文件必须对所有人可读,这样像ls这样的命令才能工作,所以系统上的所有用户都能读取到加密后的口令字符串。做坏事的人可以加密整个字典,把加密后的结果和/etc/passwd文件里的字符串进行比较。如果匹配到了加密后的字符串,那么就找出了一个口令。
这种威胁会有多大呢?早在20世纪80年代,至少就有一种方法可以非常快地解密口令[49],但是普通的黑客只得满足于使用crypt库例程[50]来加密词典中的单词以便进行比较。20世纪80年代一台“快速的”机器每秒钟可以完成几百次加密。现在使用穷举搜索在24小时内就能破解一个56位的DES密钥。幸亏现代的UNIX和Linux系统都不使用crypt,因此要安全得多。
这些结果着实令人吃惊,它们表明确实应该限制用户对加密后口令字符串的访问。常用的强制方法是把口令放在一个单独的文件中,这个文件只对root可读,而保留/etc/passwd的其余部分不动。于是这个包含实际口令信息的文件被称为隐蔽口令文件(通常是/etc/shadow)。所有的现代Linux发行版本的默认配置都支持隐蔽口令。
21.20.45.1
口令的检查和选择
坚持核实(最好是每天)每个登录名是否有口令,这很重要。在/etc/shadow文件(如果您的站点没有使用隐蔽口令的话是/etc/passwd文件)中,应该在“daemon”这样的伪用户—它们拥有文件但从不登录—的说明项里,给它们的加密口令域填一个星号(*)或者一个感叹号(!)。星号不与任何口令匹配这两个字符不与任何口令匹配,这样就可以防止使用这个账号。
/etc/shadow文件基本上用不着维护。不过下面这个只有一行的Perl程序能查找空口令:
$ sudo perl -F: -ane 'print if not $F[1];' /etc/shadow
您可以让cron运行一个脚本来执行这项检查并把结果用邮件发给您。您可以编写一个脚本,用diff命令把passwd文件与前一天的版本做比较,并把差异通过电子邮件发给您,帮助核实所有的修改行为是否合法。
21.20.45.5
2 口令时限
Linux的隐蔽口令系统还能让您强迫用户周期性地修改他们的口令,这种工具程序通常称为口令时限。这乍看之下似乎是个好主意,但它有几个问题。用户经常因为不得不修改口令而十分愤慨,由于他们不想忘掉新的口令,所以会选择一些简单的、易于键入和记住的东西。许多用户每次被强迫修改口令时就在两个口令之间来回切换,从而使口令时限失去意义。PAM模块可以帮助落实安全性强的口令,避免这个问题。
虽然如此,口令还是应该定期修改,特别是root口令。root口令应该很容易在手指上敲出来,这样就可以很快敲进去而不会被看着您的手指在键盘上移动的人猜出来。在我们的站点上,大多数人用sudo而不是真正的root口令,但我们仍然认真地选择root口令。有关sudo的更多信息请参见3.4.2节。
chage程序控制口令的时限
21.4.3
隐蔽口令
。系统管理员使用chage命令可以设定两次修改口令之间间隔的最长和最短时间,口令作废的日期,在用户口令作废前多少天警告用户,在账号自动锁定之前容许用户多少天不活动等。下面的命令把两次修改口令之间的最少天数设为2、最多天数设为90、作废日期为2007年7月31日,并且在接近作废日期的14天里警告用户:
$ sudo chage -m 2 -M 90 -E 2007-07-31 -W 14 ben
21.20.45.4
3 组登录名和共享登录名
任何由多人使用的登录名都是坏消息。组登录名(比如“guest'”或“demo“”)是黑客安家的安全地带,像HIPAA这样的联邦法律在很多情况下都会禁止这样做。。不要在您的站点上有这类登录名。
同样,不要让用户与家庭或朋友共享登录名。如果小Johnny需要一个登录名用于他的科学项目,请给他一个名符其实的登录名。一旦他滥用登录名就可以取消Johnny的登录名,这比起取消Dad与他共享的账号容易得多,尤其在政府网点上更是如此。有关共享登录名的其他建议请参考29.2节。
在大多数网点上,“root”是一个组登录名。危险!我们推荐使用sudo程序来控制对root权限的访问。参考3.4.2节。
21.20.45.6
4 用户的shell
不要用一个脚本作为无限制(无需口令没口令)登录名的shell。实际上,如果您发现自己需要一个无需口令的登录名应该只用作一种运行小的没口令的登录名,那么可能应该考虑代之以使用一个无口令词的SSH密钥对。
、非交互式实用程序,比如date、sync或lpq的工具。
21.20.45.7
5 获得root权限的办法
root登录名唯一的特别之处就在于其UID为0。因为在/etc/passwd文件中可以有多项使用这个UID,所以可以有许多种方法以所以以root身份登录可以有不止一种途径。
黑客一旦获得root shell,他们安装后门的一种常用方法就是在/etc/passed中编辑新的root登录名。像who和w这样的程序会指向/var/run/utmp中保存的名称而不是拥有登录shell的UID,因此它们不能暴露出那些看似无辜其实是以UID 0登录的黑客。
对这种欺骗的防御方法是编写类似用于发现无口令登录名的那种小脚本。
$ perl -F: -ane 'print if not $F[2];' /etc/passwd
这个脚本将打印出passwd文件中UID为空(null)或为0的所有行。您可以很容易地改写它,找出其组或UID和组织内部关键人员的组或同贵单位内部关键人员的组或UID相同的可疑项。
还应该检查passwd中是否有缺少用户名或把标点符号作为用户名的条目。这些条目可能看起来没有意义,但它们常常会允许黑客登录但它们常常会让黑客登录。
21.20.45.62
PAM:验证奇才
PAM,即Pluggable Authentication Modules(可插入式身份验证模块)最初是由Sun公司发明的,Sun把它作为一种验证用户身份的灵活方法。多年以来,UNIX环境下的身份验证机制一直就是简单地把用户同他们在/etc/passwd文件里的配置项关联起来而已。后来,因为需要有更强的安全性,而且要支持更大范围的验证机制(像智能卡),所以对灵活性更好的验证方法的需求也就应运而生。某些PAM LDAP模块对全局的验证目录集中执行验证。
(译者注:PAM也是最受美国欢迎的一种炒菜油的品牌,它的最大卖点就是不会四处乱溅。有兴趣的读者可以看看http://www.pam4you.com/里的介绍。)
所有完善的Red Hat、SuSE和DebianLinux发行版本都带Linux-PAM,它和Sun公司PAM标准目前的实现没有关系。PAM的概念很简单:需要验证功能的程序只需要知道有一个模块可以用来替它们执行验证功能就行了。PAM的设置保证了模块可以随时添加、删除和重新配置—对于编译工具程序的时候就被链接进来(甚至原本就有)的模块来说,没必要这样做。这种结构的效果就是,PAM已经成为系统管理员极其强大的工具。
PAM模块是通过/etc/pam.d目录下的文件来进行配置的。这个目录下针对每种服务的文件所包含的配置项都有如下形式:
module-type control-flag module-path arguments
module-type字段可以取的值有auth、account、session或者password。auth确定用户是谁,还可能确定他是哪一个组的成员。account实行不基于身份验证的决策,比如根据一天中的时间来访问。session实现了在提供给用户服务的前后需要完成的任务。最后,password用于要求用户提供验证信息(比如口令)的情况。
control-flag字段有4个可能的取值:required、requisite、sufficient和optional。required和optional最常用,它们分别表示:为了程序继续执行模块必须取得成功,或者模块成功与否没有关系。
第3个和第4个字段是动态加载模块对象的路径和参数。如果路径的第1个字符是/,它就被当作是一个绝对路径。否则,这个字段的内容就被追加到默认路径/lib/security的后面。
PAM是上述口令复杂性难题的解决方案之一。pam_cracklib模块能够强制要求口令符合最低强度要求。具体要求则变化多端,所以要使用grep找到正确的配置文件。例如,要保证用户口令不能被John the Ripper破解(参考20.10.3节了解有关它的更多知识),Fedora上的/etc/pam.d/system-auth应该包括:
password required pam_cracklib.so retry=3 minlen=12 difok=4
password required
pam_cracklib.so retry=3
password required
pam_pwdb.so use_authtok
有了这几行,PAM就会把用户提出的新口令同crack破解字典和规则集进行对照(这要求有系统库libcrack,和一个系统字典还有一个系统字典/usr/lib/cracklib_dict.*)。如果用户的口令不符合cracklib的要求,那么屏幕上就会出现像“The password is too simple(口令太简单)”这样的出错信息。
参数retry=3指出用户在输入一个强口令的时候必须输入三遍。有use_authtok的一行把口令模块的各层连接到了一起。
cracklib的参数规则很复杂,不过下面是对上述特定配置的解释。
参数retry=3指出用户在输入一个强口令的时候必须输入三遍。
参数minlen=12指出口令的最短长度。大写字母、数字和标点符号由库特殊处理,从而减小了这个最短长度。参数为minlen=12时,用户能有的最短口令实际为8个字符,不是12个字符,但是用户设定一个8字符口令时必须包括所有4种字符类型。
参数difok=4指出新口令至少要有4个字符不会出现在老口令中。
现代Linux发行版本包含并且默认使用pam_cracklib模块,但通常不启用口令复杂性规则。
PAM模块有数十种。您可以从www.kernel.org/pub/linux/libs/pam下载专门的模块以及它们的文档。






