你可以按照等保测评的标准要求,在Ubuntu 24.04上分步完成口令复杂度和有效期策略的整改,具体操作如下:
一、配置口令复杂度策略
先查看是否已经安装密码策略依赖模块:libpam-pwquality 是 Linux 系统(特别是基于 Debian/Ubuntu 的系统)中用于强制密码复杂度策略的核心组件。
sudo dpkg -l | grep libpam-pwqualit*输出以下:
ii libpam-pwquality:amd64 1.4.5-3build1 amd64 PAM module to check password strength输出内容解释:
- ii:这是软件包的状态标志。
第一个 i 表示期望状态为“安装”(Install)。
第二个 i 表示当前实际状态为“已安装”(Installed)。
结论:该软件包已完整且正确地安装在系统中。
- libpam-pwquality:amd64:软件包的名称及架构。
libpam-pwquality 是包名。
amd64 表示这是适用于 64 位 Intel/AMD 处理器的版本。
- 1.4.5-3build1:当前安装的版本号。
- PAM module to check password strength:软件包的简要描述,意为“用于检查密码强度的 PAM 模块”。
如未安装依赖模块,执行命令安装PAM口令强度校验组件:
sudo apt update && sudo apt install libpam-pwquality -y编辑复杂度规则文件
打开配置文件:
sudo nano /etc/security/pwquality.conf写入等保要求的核心参数:
minlen = 10 # 口令最小长度不小于10位
minclass = 3 # 至少包含3种不同字符类别
dcredit = -1 # 至少包含1个数字
ucredit = -1 # 至少包含1个大写字母
lcredit = -1 # 至少包含1个小写字母
ocredit = -1 # 至少包含1个特殊符号
maxrepeat = 2 # 禁止连续3个及以上相同字符
usercheck = 1 # 禁止口令中包含用户名关联PAM认证规则
编辑PAM配置文件:
sudo nano /etc/pam.d/common-password找到对应行,追加参数确保root用户也受策略约束:
password requisite pam_pwquality.so retry=3 enforce_for_root二、配置口令有效期策略
修改全局登录默认规则
编辑系统登录配置文件:
sudo nano /etc/login.defs调整等保要求的有效期参数:
PASS_MAX_DAYS 90 # 口令最长有效期90天
PASS_MIN_DAYS 7 # 两次修改口令的间隔至少7天
PASS_WARN_AGE 14 # 口令过期前14天开始提醒用户禁止历史口令重复使用
在/etc/pam.d/common-password文件中追加配置,记录最近5次历史口令禁止复用:
password [success=1 default=ignore] pam_unix.so remember=5三、验证策略生效
执行以下命令测试新口令是否符合规则,同时可使用chage 用户名命令查看指定账户的口令有效期配置是否正确。
在 Ubuntu 24.04 上完成口令复杂度和有效期策略配置后,需通过以下命令进行验证,确保策略已正确生效且符合等保要求:
1. 验证口令复杂度策略(PAM 模块)
检查 PAM 配置文件是否已正确加载 pam_pwquality模块及参数。
检查配置文件内容:
grep -v '^#' /etc/pam.d/common-password | grep pwquality达标判据: 输出中应包含 password requisite pam_pwquality.so 以及你设置的参数(如 minlen=10, dcredit=-1 等)。
检查 pwquality 详细配置(可选):
cat /etc/security/pwquality.conf | grep -E "minlen|minclass|dcredit|ucredit|lcredit|ocredit"达标判据: 确认各项参数值与预期一致。
实战测试(推荐):
切换到普通用户或 root 用户,尝试修改密码,观察系统是否拒绝弱口令。
passwd <用户名>尝试设置简单密码(如 123456、password),系统应提示“BAD PASSWORD”并拒绝。
尝试设置符合规则的强密码,系统应接受。
2. 验证口令有效期策略(全局默认值)
检查 `/etc/login.defs文件中的全局默认配置,这决定了新建用户的默认策略。
执行命令:
grep -E 'PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE' /etc/login.defs达标判据:
PASS_MAX_DAYS 应等于 90(或小于等于 90)。
PASS_MIN_DAYS 应大于等于 1(通常设为 7,防止频繁改密绕过历史密码检查)。
PASS_WARN_AGE 应大于等于 7(通常设为 7 或 14,提前提醒用户)。
3. 验证现有用户的实际生效状态
注意: /etc/login.defs 的修改仅对新用户生效。对于已存在的用户,必须使用 chage 命令单独设置或批量更新,否则他们的密码可能仍是“永不过期”。
查看指定用户的密码策略详情:
chage -l <用户名>达标判据:
Maximum number of days between password change 应为 90。
Minimum number of days between password change 应为 7(或你设定的值)。
Password expires 应显示具体的过期日期(而非 never)。批量检查所有普通用户(UID >= 1000)的状态:
for user in $(awk -F: '$3>=1000 && $3<65534 {print $1}' /etc/passwd); do
echo "=== User: $user ==="
chage -l "$user" | grep -E "Last|Maximum|Minimum|Warning"
done如果现有用户未生效,执行批量整改命令:
# 将所有普通用户的密码最大有效期设为90天,最小间隔7天,警告提前7天
for user in $(awk -F: '$3>=1000 && $3<65534 {print $1}' /etc/passwd); do
sudo chage -M 90 -m 7 -W 7 "$user"
done4. 验证口令历史策略(防重用)
检查是否启用了 pam_pwhistory 或 pam_unix 的 remember 参数。
执行命令:
grep -v '^#' /etc/pam.d/common-password | grep remember达标判据: 输出中应包含 remember=N(N通常为 5 或更多,等保三级建议至少 5 次,部分严格场景要求 12 次以上)。
实战测试:
修改密码为一个新强密码,然后再次尝试修改为刚刚用过的那个密码。系统应提示“Password has been already used”或类似错误并拒绝。
5. 验证空口令账户(安全基线)
确保系统中没有空口令账户,这是等保测评的必查项。
执行命令:
awk -F: '$2==""{print $1}' /etc/shadow达标判据: 无输出。如果有输出,说明存在空口令账户,必须立即锁定或设置密码。
✅ 总结:一键验证脚本
你可以复制以下脚本快速完成核心验证:
#!/bin/bash
echo "=== 1. 检查 PAM 复杂度模块 ==="
grep -v '^#' /etc/pam.d/common-password | grep pwquality || echo "[FAIL] pam_pwquality not found"
echo -e "\n=== 2. 检查全局有效期默认值 (/etc/login.defs) ==="
grep -E 'PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE' /etc/login.defs
echo -e "\n=== 3. 检查口令历史重用限制 ==="
grep -v '^#' /etc/pam.d/common-password | grep remember || echo "[WARN] remember parameter not found"
echo -e "\n=== 4. 检查空口令账户 ==="
EMPTY_USERS=$(awk -F: '$2==""{print $1}' /etc/shadow)
if [ -z "$EMPTY_USERS" ]; then
echo "[PASS] No empty password accounts found."
else
echo "[FAIL] Empty password accounts found: $EMPTY_USERS"
fi
echo -e "\n=== 5. 抽查关键用户 (root 和当前用户) 的实际策略 ==="
for u in root $USER; do
echo "--- User: $u ---"
chage -l "$u" | grep -E "Maximum|Minimum|Warning|expires"
done