简介
密码策略是确保通过密码身份验证过程保护账户的机制。系统管理员负责应用密码策略的规则,他们应该确保使用的密码不会被外人轻易地推测出来。应该在所有活跃的用户账户上设置密码策略。
密码策略的组成部分之一是检查密码到期日期和访问限制。这让系统管理员可以检查用户的密码策略中是否有不一致的地方,并采取相应措施。一般来说,通常以特别的方式检查密码策略,但是最好的方法是生成所有用户的报告。通常,要考虑的因素包括每个用户最后一次修改密码的时间、密码应该到期的时间和密码标志。密码策略是常见的审计报告需求。
本文并不讨论如何保护 AIX 或如何实现安全策略,而是讨论与密码策略相关的应该注意的属性。
回页首
密码策略概述
密码策略用来确保用户访问的系统的安全性。从本质上说,这意味着密码不是容易猜测出的,应该经常修改。当用户设置自己的密码时,会对他们施加某些规则;这些规则应该应用于所有用户,但是应用程序的所有者例外。我们来看一个基本的密码策略,它限制密码的组成。在 /etc/security/user
文件中可以找到用户账户属性,比如系统默认的或用户特有的属性。
我建议健全的密码策略至少应该包含以下规则:
在登录时,用户可以三次尝试输入正确的密码,如果到了这个次数,就锁定账户。
loginretries 3
从最后一次修改密码开始,要过多久(周数)用户才能再次修改密码?
minage 1
过多久(周数)之后用户必须修改密码?
maxage 5
在密码到期之前,应该提前几天通知用户(到期之前每天都通知)?
pwdwarntime 5
在超过 maxage
之后用户可以在几周内修改密码?在这里,-1 表示当到达 maxage
时用户必须马上修改密码。
maxexpired -1
密码中使用的最小字母字符数量。
minalpha 1
密码中使用的最小非字母字符数量。
minother 1
密码中的最小字符数量。
minlen 8
由于在前一个密码中存在而不能在新密码中使用的最小字符数量。
mindiff 2
在新密码中不能重复的字符数量。
maxrepeats 2
要经过几周才能重用以前的密码?
histexpire 26
应用程序所有者账户应该是密码策略规则的惟一例外。尤其是,他们的密码可以设置为永远不到期,还可以增加锁定账户之前尝试输入密码的次数。原因很简单:如果生产环境中的应用程序或接口被锁定了,就会影响业务。应该手工管理这些账户的属性。通常可以修改以下属性:
maxage=0 loginretries=10
应该安排修改密码的时间表,在应用程序关闭时修改密码。
如果需要以更清楚的格式向安全经理报告信息,实现密码策略会非常费时间,尤其是在处理大型企业网络时。清单 1 中的 user_defaults 脚本以可读性更好的格式提供这些信息。首先,它提取系统默认设置,然后列出 /etc/security/user
中包含的具有非系统默认属性设置的每个账户。如果属性没有系统默认值,就显示消息 '**No Defaults Set'。按照这种格式,很容易看出哪些属性有系统默认值。可以在每个远程主机上运行此脚本,然后通过对比系统默认值检查主机之间是否有差异。通过查看用户账户覆盖系统默认设置的情况,就可以判断用户的属性集对于实现的安全策略是否合法有效。
清单 1. user_defaults
#!/bin/sh # user_defaults get_defaults() { # get listing of defaults entry in /etc/security/user and present grep -p -w "default:" /etc/security/user| grep -v "*"|grep -v "default:"|grep -v "\"" >/tmp/defaults.tmp # the sed '/ //g , is athen hit the tab key sed '/^$/d;s/ //g' /tmp/defaults.tmp >/tmp/hold.tmp && \ mv /tmp/hold.tmp /tmp/defaults.tmp IFS="=" echo "Default Attributes of /etc/security/user" echo "Key Value ===========================" cat /tmp/dt | while read key value do if [ "$value" = "" ] || [ "$value" = " " ] then value=" **No Default Set" fi printf "%-15s %-15s\n" "$key" "$value" done } get_users() # get list of attributes that override the defaults and present { echo "\nUser Defined Attributes -----------------------------" > users.tmp list="" # the sed '/ /g , is a then hit the tab key list=$(grep ":" /etc/security/user | grep -v default| grep -v "*" |sed 's/\:/ /g') for users in $list do echo "[$users]" grep -p -w "$users:" /etc/security/user|grep -v "*"|sed '/^$/d;s/ / /g'|sed '1d'>users.tmp cat users.tmp | while read line do key=$( echo $line | awk -F= '{print $1}') value=$(echo $line |awk -F= '{print $2}') printf "%-15s %-15s\n" "$key" "$value" done echo "-----------------------" done } savedIFS="$IFS" get_defaults IFS="$savedIFS" get_users
user_defaults 脚本的典型输出像下面这样:
清单 2. user_defaults 脚本的典型输出
Default Attributes of /etc/security/user Key Value =========================== admin false login true su true daemon true rlogin true sugroups NONE admgroups **No Default Set ttys ALL auth1 SYSTEM auth2 NONE tpath nosak umask 022 expires 0 logintimes **No Default Set pwdwarntime 0 account_locked false loginretries 3 histexpire 26 histsize 15 minage 1 maxage 5 maxexpired -1 minalpha 1 minother 1 minlen 0 mindiff 0 maxrepeats 8 dictionlist **No Default Set pwdchecks **No Default Set User Defined Attributes ----------------------------- [root] admin true SYSTEM "compat" registry files loginretries 0 account_locked false sugroups admin,sysadmin ----------------------- [daemon] admin true expires 0101000070 ----------------------- [ukflag] admin false sugroups !fire,!cloud,earth ----------------------- [testme] admin false ----------------------- [john] admin false ----------------------- [peter] admin false ----------------------- [jane] admin false ----------------------- [plutt] admin false maxage 1 ----------------------- [spoll] admin false maxage 4 -----------------------
回页首
pwdadm 标志
pwdadm
标志让系统管理员能够控制和查看用户的密码特性。尽管可以用这个命令完成其他任务,但这是它的主要用途。基本格式是:
pwdadm -f
其中的标志是:
NOCHECK
:用户在设置密码时不需要遵守密码策略。这意味着不限制密码长度或重复字符。ADMIN
:表示只有根用户才能修改密码信息。ADMCHG
:如果设置了这个标志,那么当用户下一次登录时,会提示用户修改密码。这优先于任何maxage
设置。
pwdadm -c
上面的示例清除以前设置的所有 pwdadm
标志。
pwdadm -q
上面的示例查询 pwdadm
标志,报告设置的所有标志和最后一次修改密码的时间(如果已经设置了密码的话)。
现在给出使用 pwdadm
的示例。首先,查询 pwdadm
以查看设置的标志。在这个示例中,查询用户 alpha:
# pwdadm -q alpha alpha: lastupdate = 1267374936
在上面的输出中,可以通过 lastupdate
条目看出用户 alpha 已经设置了密码。如果 lastupdate
不存在,就说明没有设置过密码。
现在,我们来设置这个用户的 ADMCHK
标志:
# pwdadm -f ADMCHG alpha
通过查询 pwdadm
再次检查标志:
# pwdadm -q alpha alpha: lastupdate = 1267374936 flags = ADMCHG
现在,清除所有标志:
# pwdadm -c alpha
检查标志是否已经清除了:
# pwdadm -q alpha alpha: lastupdate = 1267374936
回页首
修改用户属性
要想对密码或登录属性进行全局修改,应该编辑 /etc/security/user
文件。
在默认小节中,修改希望全局实现的属性的默认值。使用 chuser
命令修改单独的用户账户。例如,可以使用以下命令把用户 charlie 的 maxage
改为三周:
# chuser maxage=3 charlie # lsuser -a maxage charlie charlie maxage=3
还可以列出用户的所有属性:
# lsuser -f charlie charlie: id=211 pgrp=staff groups=staff home=/home/charlie shell=/usr/bin/ksh gecos=charlie.suppt login=true …..
回页首
密码什么时候到期
当用户登录时,如果他们的密码即将到期,就会显示警告。但是,除非用户很守纪律,他们通常会忽视这一警告,直到密码真的到期时才会修改密码。如果是这样,肯定会有一些用户多次尝试用旧密码登录,直到超过 loginretries
允许的次数,导致账户锁定。这意味着他们要联系服务人员,要求解除账户锁定,然后才能修改密码。作为预防措施,您可以判断密码到期时间并向用户发警告电子邮件。与登录之后屏幕上出现的消息相比,用户很可能更重视警告电子邮件。对于本地身份验证,使用 pwdadm
和 lsuser
命令显示属性,判断下一次修改密码的时间或密码到期时间。
正如前面指出的,密码的到期时间由 maxage 属性控制。例如:
maxage=0
意味着永远不到期
maxage=2
意味着两周后到期
AIX(UNIX® 和 Linux®)按纪元格式存储以秒为单位的时间,所以首先必须知道一周有多少秒,因为 maxage
以周为单位确定密码到期时间。
一天有 86400 秒,乘以 7 得到 604800。所以一周有 604800 秒。
下面需要使用 pwdadm
命令,这个命令查询 /etc/security/passwd
文件。这个文件包含用户最后一次修改密码的时间(以秒为单位的值)。直接查询此文件或使用 pwdadm
命令会返回相同的结果。现在,我们来查询用户 spoll:
# grep -p "spoll:" /etc/security/passwd spoll: password = EvqNjMMwJzXnc lastupdate = 1274003127 flags = ADMCHG # pwdadm -q spoll spoll: lastupdate = 1274003127 flags = ADMCHG
在上面的输出中可以看到以秒为单位的 lastupdate
值。这就是最后一次修改密码的时间:
1274003127
接下来,使用 lsuser
或直接查询 /etc/security/user
文件,查明用户 spoll 的密码到期之前的周数:
# grep -p "spoll:" /etc/security/user spoll: admin = false maxage = 4 # lsuser -a maxage spoll spoll maxage=4
在上面的输出中可以看到密码到期之前的周数是 4。
下一步是把密码到期前的周数(在这里是 4)乘以每周的秒数:
604800 * 4 # expr 604800 \* 4 2419200
接下来,需要把以秒为单位的 maxage
值 (604800 * 4) 与最后一次修改密码的时间相加:
2419200 + 1274003127 # expr 2419200 + 1274003127 1276422327
现在,可以把时间由 UNIX 纪元以来的秒数转换为更有意义的时间形式。可以使用不同的工具,本文使用 gawk 和 strftime
函数:
# gawk 'BEGIN {print strftime("%c",'1276422327')}' Sun Jun 13 10:45:27 BST 2010
这会提供下一次密码到期的时间。
现在知道了用户 spoll 最后一次修改密码的时间(来自 pwdadm
命令):
# gawk 'BEGIN {print strftime("%c",'1274003127')}' Sun May 16 10:45:27 BST 2010
和到期时间:
Sun Jun 13 10:45:27 BST 2010
现在可以判断密码什么时候到期。可以方便地循环遍历所有用户并生成报告。生成报告(尤其是在接受审计时)可以避免逐一提取信息的繁琐任务,节省大量时间。生成报告之后,可以通过打印或电子邮件把报告提交给安全管理员审查。根据我的经验,审计员愿意看到包含所需的所有属性的报告,而不是专门的屏幕图。报告还可以提醒系统管理员确保在所有服务器上以标准方式实现密码策略。可以通过查看报告发现不同用户的密码策略之间不一致的地方。
在理想情况下,报告至少应该包含每个用户的以下密码属性:
- maxage
- pwdadm 标志集
- 最后一次修改密码的日期
- 下一次修改密码的日期
清单 4 中的脚本会生成这样的登录密码属性报告。执行这个脚本时,会生成用户的密码属性报告。在我的系统上产生的输出见 清单 3。仔细看一下清单 3,它包含 5 列:
- User:实际用户
- Change weeks:下一次应该修改密码之前的周数(maxage 值)
- Last change password:最后一次修改密码的日期
- Flags:pwdadm 标志集
- Next change password:下一次应该修改密码的日期
清单 3. next_pwch 命令
# next_pwch1 user change last change flags next change weeks password password root 0 Sun Feb 21 09:44:59 GMT 2010 daemon 0 password never set charlie 0 Sun Feb 28 16:35:36 GMT 2010 foxtrot 5 Sat Feb 20 19:25:48 GMT 2010 Sat Mar 27 19:25:48 GMT 2010 kilo 5 Mon May 17 09:38:57 BST 2010 NOCHECK Mon Jun 21 09:38:57 BST 2010 xray 0 Sun Feb 28 16:42:20 GMT 2010 jane 0 password never set plutt 1 Sat Apr 24 20:21:17 BST 2010 Sat May 1 20:21:17 BST 2010 spoll 4 Sun May 16 10:45:27 BST 2010 Sun Jun 13 10:45:27 BST 2010 foxtrot 5 Sat Feb 20 19:25:48 GMT 2010 ADMCHG Sat Mar 27 19:25:48 GMT 2010
清单 3 显示我系统上的用户。我可以通过这个报告了解到以下情况:
- 用户 daemon 和 jane 没有设置过初始密码。
- 用户 root、charlie 和 xray 没有 next change password 条目;这是因为账户上设置了
maxage=0
(密码永远不到期)。 - pwdadm NOCHECK 标志表明,用户 kilo 不必遵守密码规则。
- 用户 foxtrot 的账户上设置了
pwdadm
ADMCHG 标志。这意味着他在下一次登录时必须修改密码。
很容易修改此脚本以包含 rlogin、login、su
等其他用户属性。
清单 4. next_pwch
!/bin/sh # next_pwch # display date of next passwd change # maxage value is in number of weeks # secs in a day is:86400 ..so secs_in_week=604800 log=/home/dxtans/next_pwch.log >$log myhost=`hostname` mydate=`date +"%d-%m-%y"` echo " Date: $mydate" >>$log echo "Local Password Expiry $myhost">>$log list=$(lsuser -a registry ALL|grep -w files| awk '{print $1}') echo "user change last change flags next change" echo " weeks password password" for user in $list do wks_before_ch=$(lsuser -a maxage $user | awk -F '=' '{print $2}') if [ "$wks_before_ch" = "" ] then # krb5 / ldap /limbo" expire="??" else expire=$wks_before_ch fi last_ch_pw=$(pwdadm -q $user | grep last | awk '{print $3}') # echo "last pw change : $last_ch_pw" if [ "$last_ch_pw" = "" ] then passset="password never set" else last_ch_pw_conv=$(gawk 'BEGIN {print strftime("%c",'$last_ch_pw')}') last_pw_ch=$last_ch_pw_conv passset=$last_pw_ch total_secs=$(expr $secs_in_week \* $wks_before_ch) #echo "total secs: $total_secs" # weeks + last pw change date_to_ch=`expr $total_secs + $last_ch_pw` pw_flags=$(pwdadm -q $user | grep flags | awk '{print $3}') pw_flags=$pw_flags # now convert to normal next_pw_ch=$(gawk 'BEGIN {print strftime("%c",'$date_to_ch')}') fi #echo "..$user..$wks_before_ch..$passset" if [ "$wks_before_ch" = "0" ] then next_pw_ch="" else next_pw_ch=$next_pw_ch fi if [ "$passset" = "password never set" ] then #echo "..$user.." next_pw_ch="" fi printf "%-8s %-2s %-28s %-10s%-28s\n" "$user" "$expire" "$passset" "$pw_flags" "$next_pw_ch" done
回页首
结束语
生成用户安全属性报告有助于判断和识别密码或安全策略中是否有不一致的地方。如果您控制许多远程主机,最好从部署服务器通过 SSH
运行本文中提供的脚本,然后把生成的报告发送给系统管理员。