Skip to content

17.2 账户认证安全

FreeBSD 通过 /etc/master.passwd 主密码文件与 pam_unix.so 认证模块实现账户安全管理。本节介绍密码数据库生成流程、账户锁定与 nologin 禁止登录、SHA-512 哈希验证及 pam_passwdqc 密码策略配置。

17.2.1 密码文件目录结构

/etc/master.passwd 是主密码文件,仅 root 可读,内含用户加密后的密码。

/etc/passwd 仅为兼容而保留,由 pwd_mkdb(8) 自动生成,密码字段替换为 *

sh
/etc/master.passwd

  pwd_mkdb(8)

────────────────────────────
      数据库生成过程
────────────────────────────

        ├──────────────┬──────────────┐

/etc/pwd.db     /etc/spwd.db     /etc/passwd
(db(3)格式)    (db(3)格式)     (ASCII 密码兼容文件)
(无密码)        (含密码)        (无密码)

为保证数据一致性,所有密码文件均不应手动编辑,应使用 vipw(8)、chpass(1) 或 pw(8) 等工具修改。

17.2.2 阻止登录

保护系统的首要措施是审计账户,禁用所有不需登录的账户。

思考题

确保 root 拥有强密码,定期轮替,且不应共享该密码。

此说法较为流行,实则存在安全隐患:

  • 强密码复杂难记,致使用户依赖不安全的存储方式(如纸质记录或文本文件),反而增加安全风险。
  • 定期更换密码加剧管理难度,而“密码管理工具”本身的信任问题也难以回避。
  • 基于密钥的认证方式虽提供了一定安全保障,但密钥一旦丢失,身份验证将更加复杂。
  • 多因素认证(MFA)虽能增强安全性,但其依赖的设备遗失或程序卸载后,将引发同类问题。

拒绝账户登录有两种方式,具体如下。

其一,锁定账户。下面演示如何锁定账户 ykla

sh
# pw lock ykla

锁定后,用户 ykla 尝试登录:

sh
FreeBSD/amd64 (ykla) (ttyv1)

login: ykla
Password:
Login incorrect
login:

其他用户尝试切换至 ykla

sh
# su ykla
su: Sorry

警告

切勿尝试锁定 root 账户。

sh
ykla@ykla:~ $ su
Password:
su: Sorry

否则可能需要进入单用户模式才能恢复。

解锁用户 ykla

sh
# pw unlock ykla

其二,将 shell 设为 /usr/sbin/nologin,以此阻止登录。用户尝试登录时,nologin shell 阻止系统分配 shell。

仅 root 有权更改其他用户的 shell:

sh
# chsh -s /usr/sbin/nologin ykla

用户 ykla 登录受阻,效果与前例类似。

要恢复登录,重新为用户 ykla 分配 sh:

sh
# chsh -s sh ykla

警告

切勿尝试为 root 账户分配 /usr/sbin/nologin

17.2.3 密码哈希

既然必须使用密码,密码就应当足够复杂,并以强哈希机制加密后存入密码数据库。FreeBSD 的 crypt() 库支持 SHA-256、SHA-512、Blowfish 等多种算法。

不应将默认的 SHA-512 降级为更弱的哈希算法,也不应替换为 Blowfish。

Blowfish 算法不属于 AES 家族,也不符合联邦信息处理标准(FIPS)要求,部分环境可能无法通过合规审查;同时因其分组长度过短,安全性已不被认可。

17.2.3.1 查看当前用户密码使用的哈希

如果要确认用户所用哈希算法,root 用户可查看 FreeBSD 密码数据库中对应哈希值。每个哈希值均以一个符号开头,表明加密该密码的哈希机制类型:

sh
$编号$盐$哈希

 ├── DES      : 无编号
 ├── MD5      : $1$
 ├── bcrypt   : $2a / $2b / $2y
 ├── NT-Hash  : $3$
 ├── SHA-256  : $5$
 └── SHA-512  : $6$
编号 4 未使用。

本例中,ykla 的密码以 $6$ 开头,即采用默认的 SHA-512 算法。

sh
# grep ykla /etc/master.passwd

注意,密码数据库中存放的是加密后的哈希值,而非原始密码。输出应类似于以下内容:

sh
ykla:$6$SqMJXrv5aC6Wq.by$nmbZs078aHNBVyh9noLFouJsGHyFSvQIzH0W4zpdfXuPtGtt.FHgWfXDHVBa.g9P0eZ32UwfByzRKdVnTaO7W.:1001:1001::0:0:User &:/home/ykla:/bin/sh

17.2.3.2 在登录类别中设置默认密码哈希

passwd_format 默认值为 sha512,有效值包括 desmd5blfsha256sha512(参见 crypt(3))。NIS 客户端如果使用非 FreeBSD NIS 服务器,通常应使用 des

运行以下命令可检查当前所用哈希机制:

sh
# grep passwd_format /etc/login.conf

输出应类似于以下内容:

ini
	:passwd_format=sha512:\
#	:passwd_format=des:\ # 这是注释行,可忽略

例如,要切换为 Blowfish,可将该行修改为:

ini
:passwd_format=blf:\

接着,必须执行 cap_mkdb 来更新 login.conf 数据库:

sh
# cap_mkdb /etc/login.conf

注意,此更改不会影响已有的密码哈希。也就是说,所有用户都需要运行 passwd 修改一次密码,才能让新算法生效。

17.2.3.3 密码策略执行

为本地账户实施强密码策略,属于系统安全基本配置。FreeBSD 以内置的可插拔认证模块(PAM)控制密码长度、强度与复杂度。

本节使用 pam_passwdqc 模块(用户修改密码时生效)设置密码最短与最长长度,并强制混合字符。

思考题

强制要求密码混合字符,密码轮替、禁用常见词汇等复杂性规则,已不再视作最佳安全实践。

分析这两种安全哲学。

配置时先切换至 root 用户,然后取消 /etc/pam.d/passwd 文件中 pam_passwdqc.so 所在行的注释。

sh
#
#
# PAM configuration for the "passwd" service
#

# passwd(1) does not use the auth, account or session services.

# password
#password       requisite       pam_passwdqc.so         enforce=users # 注意此行,移除行首的 # 符号
password        required        pam_unix.so             no_warn try_first_pass nullok

然后依策略编辑该行:禁用第一至第三类密码(含密码短语),仅允许四类字符密码(≥10 位)或三类字符密码(≥12 位);新旧密码不得相似;失败最多重试 3 次;仅对普通用户强制执行(root 不受约束)。

ini
password        requisite       pam_passwdqc.so         min=disabled,disabled,disabled,12,10 similar=deny retry=3 enforce=users

参数含义:

min=disabled,disabled,disabled,12,10 对应五种密码复杂度:

  1. 仅一种字符类(disabled, 禁用)
  2. 仅两种字符类(disabled, 禁用)
  3. 密码短语(disabled, 禁用)
  4. 包含三种字符类(启用但最小 12 位)
  5. 包含四种字符类(启用但最小 10 位)

字符类包括:数字、小写字母、大写字母和其他字符。非 ASCII 字符如果无法归类,视作非数字类。

保存文件后,用户修改密码时会看到类似下面的提示:

sh
$ passwd

输出应类似于以下内容:

text
Changing local password for ykla
Old Password:

You can now choose the new password.
A valid password should be a mix of upper and lower case letters,
digits and other characters.  You can use a 12 character long
password with characters from at least 3 of these 4 classes, or
a 10 character long password containing characters from all the
classes.  Characters that form a common pattern are discarded by
the check.
Alternatively, if noone else can see your terminal now, you can
pick this as your password: "embark,France_list".

密码如果不符合策略,系统拒绝并给出警告,例如:

sh
Weak password: too short.

用户可在配置的重试次数内多次尝试。

如果组织要求密码定期过期,FreeBSD 可在 /etc/login.conf 的用户登录类别中设置 passwordtime 参数。

default 登录类别中包含一个示例:

ini
#       :passwordtime=90d:\

要为此登录类别设定 90 天过期,移除注释符(#),保存后执行:

sh
# cap_mkdb /etc/login.conf

如果要为单个用户 ykla 设置过期时间,可向 pw 同时传递过期日期(或距离过期的天数)和用户名:

sh
# pw usermod -p 31-05-2026 -n ykla

过期日期以日、月、年的格式设置(dd-mm-yy[yy])。

如需取消密码过期限制,将过期时间设为 0 即可。

sh
# pw usermod -p 0 -n ykla

也可以指定相对日期。从今天起,指定用户 ykla 在 30 天后过期:

sh
# pw usermod ykla -e +30d

从今天起,指定用户 ykla 在一年后过期:

sh
# pw usermod ykla -e +1y

17.2.4 课后习题

  1. 在 FreeBSD 中,/etc/master.passwd 文件中存储的密码哈希值以 $6$ 前缀开头,查阅资料说明该前缀对应的哈希算法,并与 $2b$ 前缀进行安全性对比。

  2. 使用 pw lock 命令锁定一个测试账户后,分别通过本地终端和 SSH 尝试登录,记录两次尝试的错误信息差异。