已索引

Password Aging

  • Historically, passwords were stored in /etc/passwd, however this file must be world readable because commands such as /bin/ls need to access it to map user lD numbers (UlDs) to user names.
  • Passwords were migrated to the more secure /etc/shadow file. As long as encrypted passwords are being stored in a dedicated file, password aging policy and data can be stored as well.

Review: /etc/shadow Fields

  1. Username
  2. Password hash
  3. Date of last password change (number of days since 1970.01.01)
  4. Minimum password age (in days, 0 = no minimum age requirement)5.
  5. Maximum password age (in days)
  6. Password warning period (in days, 0 = no warning given)
  7. Password inactive period (in days)
  8. Account expiration (number of days since 1970.01.01)
    帐户有效期一般用于临时帐号,试用帐号等场景。

在password expiration date之前,用户都可以使用旧密码登陆系统。默认inactive days为,表示用户密码过期后,随时都可以使用过期密码登陆系统,系统会立马强制要求修改密码,否则不让使用系统(即宽限期无限长)。如果设置为0,表示,用户密码一过期,则系统不再给你使用过期密码登陆登录和修改密码的机会,此时,你必须联系管理员,如果设置为3,则表示密码过期后3天内,你可以使用过期密码登陆系统,登录后系统会立马强制要求你修改密码,否则不让使用系统。

Review: chage

# chage -m 3 -M 90 -W 7 -I 356 username
# chage -l username

注意这儿是字母i的大写I,表示设置 inactive days,-1表示将该值移除,置空,即宽限期无限长。注意,-I 只有在设置了密码过期时才能通过 chage -l username 看到效果。

# chage -d 0 username

强制下次登录时修改密码。注意这儿是零而不是欧。-d表示--lastday,chage -d 1970-01-01 student表示student在很早很早修改了密码,所以现在必须修改密码,也可以使用天数0。对一个用户执行了 chage -d 0 username后,该在下次登录后必须立即修改密码。

# date
Tue May 28 16:35:06 CST 2024

# chage -l cy
Last password change                                    : May 28, 2024
Password expires                                        : Jun 27, 2024
Password inactive                                       : Jun 27, 2024
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 30
Number of days of warning before password expires       : 7

Password inactive与Password expires是同一天,用户cy已经完全没有登录系统的机会了,此时,他必须联系系统管理员进行密码修改。

# chage -d 0 cy
# chage -l cy
Last password change                                    : password must be changed
Password expires                                        : password must be changed
Password inactive                                       : password must be changed
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 30
Number of days of warning before password expires       : 7

管理员响应后,用户cy又有了使用旧密码登录系统的机会,登录后系统会立即要求修改密码。

再比如:

# chage -l cfop
Last password change                                    : May 28, 2024
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

看到cfop用户的密码是永不过期的。

# chage -M 5 cfop
# chage -l cfop
Last password change                                    : May 28, 2024
Password expires                                        : Jun 02, 2024
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 5
Number of days of warning before password expires       : 7

Default Password Aging Policy

  • Default password aging values are defined in /etc/login.defs
  • The useradd command and other user management commands use this file to determine default values for fields in /etc/shadow
  • Implement a default maximum password age of 60 days and require a password to be 3 days old before it can be changed
# grep -v ^# /etc/login.defs | grep -v ^$
MAIL_DIR        /var/spool/mail
PASS_MAX_DAYS   99999
PASS_MIN_DAYS   0
PASS_MIN_LEN    5
PASS_WARN_AGE   7
UID_MIN                  1000
UID_MAX                 60000
SYS_UID_MIN               201
SYS_UID_MAX               999
GID_MIN                  1000
GID_MAX                 60000
SYS_GID_MIN               201
SYS_GID_MAX               999
CREATE_HOME     yes
UMASK           077
USERGROUPS_ENAB yes
ENCRYPT_METHOD SHA512

PAM

  • Pluggable Authentication Modules

    • A generic framework for applications which must handle authentication authorization of users
  • Centralized, shared code base
  • Dynamically configurable

    • Install a new module to add new authentication methods or other capabilities
    • Edit application's PAM configuration, changes take effect immediately
  • PAM returns success or failure to the calling application

PAM是顺应第三方认证而生的。可以想像,最开始的时候,Linux使用/etc/passwd做认证,所以应用程序使用/etc/passwd做认证,后来linux使用/etc/shadow做认证,所以全部的应用都需要代码重写来使用/etc/shadown做认证,再后来,linux支持了第三方认证例如LDAP,于是全部的应用又要全部重写以支持LDAP。有了PAM模块后,应用可以通过其对应的PAM配置文件来调用相关的PAM,避免代码的重写。现在,Linux的标准认证体系也嵌入到了PAM中。

PAM Configuration

  • 帮助手册

    • /usr/share/doc/pam-1.1.1/
    • 可以看总文件Linux-PAM_SAG.txt,也可以看txt或者html目录下的各个模块的帮助文件。
  • /lib[64]/security/ contains PAM modules
  • /etc/pam.d/ contains configuration files for the applications that use PAM

    • Determines which modules are used by which applications, in what order
    • Configuration file used normally has the same name as the service using PAM
    • /etc/security/ contains supplementary configuration files for some PAM modules
  • Four functional management groups

    • auth: Authentication of the user 用来判断用户是用户本人(例如通过密码校验)
    • account: ls the account okay to use? 有时密码输对了不代表你能使用系统,因为帐号可能过期或者在黑名单中
    • password: Authentication token updates 专门为修改密码而准备的,让用户修改一个符合要求的密码
    • session: Session management 可用于规范用户的行为,例如控制用户的资源使用(limits.conf就是基于它)。
    • Each of these groups is independent
    • A module need not support all four groups
  • Simple Control Values

    • required: Check must pass for authentication to succeed, and keep checking modules whether we pass or fail (use requisite to fail immediately)
    • sufficient: If this check and all prior required checks passed, authentication immediately succeeds; otherwise no effect on overall pass/fail
    • optional: Pass or fail does not affect success
      required必须满足要求,如果检查失败,不退出,继续向后。requisite必须满足要求,如果检查失败,立即退出。sufficient表示如果之前的required通过并且我这儿通过,则立即通过,如果我这儿没通过,没关系,当我不存在。optional纯粹打酱油,检查结果对最结果结果没有任何影响。
  • include Control Value

    • The include control value includes all the checks for this management group from another PAM service configuration file at this point in the file
    • The checks from the other file are each performed as if they were inserted into this file individually at that point:
    • 一般说来,system-authpassword-auth这两个是linux最核心的认证档案归档文件,经常被包含到应用的PAM配置文件中,前者比较倾向于控制本地认证,例如login。后者倾向于控制远程认证,例如sshd。

pam_cracklib.so 密码复杂度检查

参考文件:/usr/share/doc/pam-1.1.1/html/sag-pam_cracklib.html
The pam_cracklib.so module

  • Prompts for the new password
  • Checks password against rules and a database(该模块主要用来做密码的复杂度检查)
  • Passes password to the next stacked module
# grep ^password /etc/pam.d/system-auth
password    requisite     pam_cracklib.so try_first_pass retry=3 type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

选项说明:

  • try_first_pass
    Which allows pam_cracklib.so to use the password collected from the user by the application calling PAM. 这是 RHCA 培训时,老师课件上写的,意为允许该PAM模块使用(调用PAM模块的应用从用户那儿获得的)密码。联机手册上关于该参数的解释是:Before prompting the user for their password, the module first tries the previous stacked module's password in case that satisfies this module as well. 意即该模块首先应当使用前一个模块从用户那里得到的密码,如果该密码验证不通过,再提示用户输入新的密码。注意,在模块文档中没有该参数的说明,在 Linux-PAM_SAG.txt 文件中有关于该参数的说明。
  • retry=3
    Where a user is given three chances to provide a password. 这是RHCA培训时,老师课件上写的。模块手册上的说明:Prompt user at most N times before returning with error.
  • type=string
    Define the type string displayed in a new password prompt. 这是RHCA培训时,老师课件上写的。模块手册上的说明:Alias for authtok_type kept for backwards compatibility. 而关于 authok_type,文档上的说明为:The default action is for the module to use the following prompts when requesting passwords: "New UNIX password: " and "Retype UNIX password: ". The example word UNIX can be replaced with this option, by default it is empty.
  • minlen=N
    The minimum acceptable size for the new password (plus one if credits are not disabled which is the default). In addition to the number of characters in the new password, credit (of +1 in length) is given for each different kind of character (other, upper, lower and digit).
  • dcredit=N
    (N >= 0) This is the maximum credit for having digits in the new password. If you have less than or N digits, each digit will count +1 towards meeting the current minlen value. The default for dcredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of digits that must be met for a new password.
  • ucredit=N
    (N >= 0) This is the maximum credit for having upper case letters in the new password. If you have less than or N upper case letters each letter will count +1 towards meeting the current minlen value. The default for ucredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of upper case letters that must be met for a new password.
  • lcredit=N
    (N >= 0) This is the maximum credit for having lower case letters in the new password. If you have less than or N lower case letters, each letter will count +1 towards meeting the current minlen value. The default for lcredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of lower case letters that must be met for a new password.
  • ocredit=N
    (N >= 0) This is the maximum credit for having other characters in the new password. If you have less than or N other characters, each character will count +1 towards meeting the current minlen value. The default for ocredit is 1 which is the recommended value for minlen less than 10. (N < 0) This is the minimum number of other characters that must be met for a new password.
  • minclass=N
    The minimum number of required classes of characters for the new password. The default number is zero. The four classes are digits, upper and lower letters and other characters.

示例(注意实验中minlen的效果):
password requisite pam_cracklib.so try_first_pass retry=3 type= ocredit=-1 dcredit=-2 minlen=8
password requisite pam_cracklib.so try_first_pass retry=3 type= ocredit=2 dcredit=2 minlen=12
在第二个示例中,ocredit=2表示,当密码长度不足minlen时,最多可以用两其它字符,每个字符+1。ocredit=2也可以理解为最多有2个特殊符号可以补位(每个字符算两个),效果是一样的。dcredit类似。如果某类字符没有指定(默认<X>credit=1),表示在给出的密码中,该类字符中的一个字符可以算两个,其它该类字符算一个,例如:ocredit=-1 dcredit=-2 minlen=8,没有提到大、小写字母,所以允许一个大写字母算两位(只有一个大写字母算两位,其它仍然算一位),允许一个小写字母算两位(只有一个小写字母能算两位,其它仍然算一位)。所以,!23aA2可以(长度为6+2),!23MA2(长度6+1)不可以。

修改两个文件system-auth 和password-auth:
password requisite pam_cracklib.so try_first_pass retry=3 type=Windows dcredit=-1 ucredit=-1 ocredit=-1 minlen=10
这样一来,用户修改密码的时候,密码必须至少一个数字,一个大写,一个特殊字符,长度为10.

# su - xuwang
$ passwd
Changing password for user xuwang.
Changing password for xuwang.
(current) UNIX password: 
New Windows password: 
Retype new Windows password: 
passwd: all authentication tokens updated successfully.

这儿设置的密码是X5!45465uk(10个字符),我们再尝试将密码修改为kb78?5Y8p(9个字符)发现也可以成功,这是因为,上在的规则中没有定义lcredit,则其默认值 是lcredit=1,表示有一个小写字母可以算+1个字符。再次尝试将密码设置为?t!X39a7(只有8个字符)就不成功了。

pam_tally2.so 失败登录锁定

这个模块主要用来防止暴力破解。如果用户登录失败达到指定次数,就禁止该用户登录,直到到达解锁时间。
该模块功能的缺点就是容易被Dos,黑客不停地用你的帐号去尝试,将导致你的帐户一直被锁,你也不能使用了。

/etc/pam.d/system-auth, password-auth

auth        required      pam_env.so
auth        required      pam_tally2.so deny=3 unlock_time=120  ## 失败3次锁定,120s自动解锁
auth        sufficient    pam_fprintd.so
auth        sufficient    pam_unix.so nullok try_first_pass
……
account     required      pam_tally2.so   ## 用户被锁定后,即使他输入了正确的密码,也会被拒绝
account     required      pam_unix.so  ## 实验效果是不要这一行是一样的
……

现在开两个终端,在一个终端上执行ssh username@localhost尝试登陆,输入错误的密码,每尝试一下,都在另外一个终端上执行pam_tally2来查看登陆失败的效果。尝试3次后,用户将被锁定,此时,用户即使给出了正确的密码也会被拒绝,即使root为其重置了密码也不行,120s后,用户将被解锁。用户使用正确的密码成功登录后,或者 root 重置了失败次数后,失败记录次数将被重置。

人工解锁:
pam tally2 ## 查看失败记录report failed logins
pam tally2 --reset -u username ## 解锁

选项解释:
该模块选项分为GLOBAL、AUTH、和ACCOUNT选项,作用不同区域,选项也不同,具体看手册。

  • onerr=[fail|succeed]
    If something weird happens (like unable to open the file), return with PAM_SUCCESS if onerr=succeed is given, else with the corresponding PAM error code.
  • lock_time=n
    Always deny for n seconds after failed attempt. 只要用户输错密码,立马锁定指定时间,并告之用户解锁需要的等时间(unlock_time不会告之),而不是说失败了多少次后才锁定。
  • even_deny_root
    Root account can become unavailable.
  • root_unlock_time=n
    This option implies even_deny_root option. Allow access after n seconds to root account after failed attempt. If this option is used the root user will be locked out for the specified amount of time after he exceeded his maximum allowed attempts.
  • magic_root
    如果是root登录失败,可以在pam_tally2中看到登录失败的次数,但是只要root给出了正确的登录密码,就可以登录系统。这是因为magic_root参数的作用。官文档的说明是:If the module is invoked by a user with uid=0 the counter is not changed. The sysadmin should use this for user launched services, like su, otherwise this argument should be omitted.

limits.conf - User Session Control 资源限制

man 5 limits.conf:
Note that all limit settings are set per login. They are not global, nor are they permanent; existing only for the duration of the session. One exception is the maxlogin option, this one is system wide. But there is a race, concurrent logins at the same time will not always be detected as such but only counted as one.

  • Modules that use a supplementary configuration file in /etc/security are called as session type rules
  • limits.conf file belongs to the pam_limits.so module and is used to place limits, sometimes also referred to as user limits or ulimits, on users logging onto the system

    • core - limits the core file size (KB)
    • data - max data size (KB)
    • fsize - maximum filesize (KB)
    • memlock - max locked-in-memory address space (KB)
    • nofile - max number of open file descriptors
    • rss - max resident set size (KB)
    • stack - max stack size (KB)
    • cpu - max CPU time (MIN)
    • nproc - max number of processes
    • as - address space limit (KB)
    • maxlogins - max number of logins for this user
    • maxsyslogins - max number of logins on the system
    • priority - the priority to run user process with
    • locks - max number of file locks the user can hold
    • sigpending - max number of pending signals
    • msgqueue - max memory used by POSIX message queues (bytes)
    • nice - max nice priority allowed to raise to values: [-20, 19]
    • rtprio - max realtime priority

例如,限制用户单个进程最大的CPU使用时间:

# vim /etc/security/limits.conf
xuwang          hard    cpu             1

这样一来,用户xuwang的单个进程使用CPU的时间不能超过1分钟,超过1分钟该进程则会被kill掉。用xuwang的身份来执行dd=/dev/zero of=/dev/null来消耗CPU,root在另外一个终端中使用top命令观察dd命令CPU的使用情况。会发现,1分钟的时候,dd命令被killed了。

再如,允许用户 visitor 至多同时开 2 个会话

# vim /etc/security/limits.conf
visitor hard maxlogins 2

生产中经常遇到的一个问题就是关于进程数量的限制。
默认情况下,root 不受限制,普通用户会受到 soft 限制,根据OS版本不同,值也可能不同,通常来说,RHEL6是1024,RHEL7是4096。具体可以查看系统的默认配置:

# cat /etc/security/limits.d/90-nproc.conf
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.

*          soft    nproc     1024
root       soft    nproc     unlimited

可以看到,这是一个软限制。普通用户可以查看并设置该值:
$ ulimit -a
……
max user processes (-u) 1024
……
使用 -u 选项可以查看/设置最大进程数的限制:
$ ulimit -u 2048 ## 设置
$ ulimit -u ## 查看
2048

那既然普通用户能改,这个有什么意思呢?业界我们称它为反bash炸弹,主要是用来防止fork炸弹(bash炸弹),防止普通用户不小心执行了一个奇怪的程序导致整个系统HUNG住。

一个不受限制的用户执行如下命令,将导致系统卡死。
$ :(){ :|:& };:
这条命令的实质是如下的shell脚本:

bomb()
{
    bomb|bomb&
};
bomb

这个脚本定义了一个函数bomb,在这个函数中调用自己两次。在最后使用这个函数。这样一来,1生2,2生4,4生8……系统很快就被累死了。上面的命令是将函数名替换成了冒号:。

在配置进程数限制时,一定要注意子配置文件是否存在。如果子配置文件存在,即使在 limits.conf 中做了配置,也会以子配置文件中的值为准,在 RHEL7 的 /etc/security/limits.conf 文件中有这样一段注释说明:

#Also note that configuration files in /etc/security/limits.d directory,
#which are read in alphabetical order, override the settings in this
#file in case the domain is the same or more specific.
#That means for example that setting a limit for wildcard domain here
#can be overriden with a wildcard setting in a config file in the
#subdirectory, but a user specific setting here can be overriden only
#with a user specific setting in the subdirectory.

建议将进程数量纳入监控。不用专门针对业务用户的进程数量进行监控,可直接监控所有的进程数量。业务用户的进程数量异常也会体现在总的进程数量里:

# ps -eLf | wc -l

PAM 故障实例

一台linux主机安装了oracle数据库,从console口登录时一闪就退出了,使用图形化界面和xshell可以登录。
解决问题的思路:只是console登录出问题,说明应该是控制台登录的PAM模块出了问题,定位到/etc/pam.d/login,检查到其中有一行:
session required /lib/security/pam_limits.so
去检查发现文件/lib/security/pam_limits.so根本不存在,因为该系统是64位,改为/lib64/security/pam_limits.so后正常。

-- By 许望(RHCA、OCM、VCP)
最后修改:2024 年 05 月 30 日 12 : 28 PM
如果觉得我的文章对你有用,请随意赞赏