PAM配置错误如何导致权限提升?
在一次内部审计中,安全团队意外发现一台生产服务器的 /etc/pam.d/sshd 文件多了一行 user_readenv=1,而这本应仅在本地控制台登录时才开启的 allow_active 标记被错误地暴露给了远程 SSH 会话。看似微小的配置偏差,却为攻击者提供了直接跳过身份验证的通道,最终让普通用户在数秒内获得了 root 权限。

PAM 的核心机制
PAM(Pluggable Authentication Modules)通过一系列堆叠的 module,在登录、密码变更、会话管理等环节执行统一的策略。每个 module 可以返回 success、ignore、deny 等结果,系统根据 control flag(如 required、sufficient)决定是否继续向下执行。这种高度可组合的设计在提升灵活性的同时,也把配置错误的风险放大了数倍。
典型的 PAM 配置错误
- 在
sshd或login服务中误将pam_unix.so的nullok选项保留,导致空密码可直接通过。 - 使用
pam_env.so的readenv=1或user_readenv=1,让远程用户可以读取或写入环境变量,从而触发allow_active。 - 将
pam_permit.so置于required前置,等同于在认证链中插入了一个永远返回 success 的后门。 - 在
common-auth中混用pam_deny.so与pam_permit.so,导致控制流不可预测。
权限提升的攻击路径
攻击者通常先通过公开的 SSH 端口获取普通账号,随后利用上述 user_readenv=1 触发的 allow_active,在 pam_policy 中获得 “active” 状态。此状态会被 polkit 误判为本地登录用户,从而在调用 udisks2、systemd-logind 等 D‑Bus 服务时跳过二次认证。借助 udisks2 的块设备管理接口,攻击者可以执行 mount -o rw,exec /dev/sda1 /mnt,随后在挂载点写入 SUID 二进制或直接覆写 /etc/shadow,完成 root 权限的夺取。
防御要点
- 审计所有
/etc/pam.d/*文件,确保user_readenv、readenv仅在必要的本地登录模块中出现。 - 对关键服务(如 SSH、su、sudo)使用
required的pam_deny.so作为最后一道防线,防止意外的pam_permit.so覆盖。 - 在 polkit 规则中显式要求管理员认证,例如在
/etc/polkit-1/rules.d/50-local.rules中加入Result.AUTH_ADMIN,阻止 “allow_active” 的默认放行。 - 开启
auditd对 PAM 模块调用的审计日志,配合ausearch -m USER_AUTH及时捕获异常登录链。
“一次看似无害的环境变量读取配置,足以让远程攻击者站在系统的最高点。”——安全架构师刘晨

参与讨论
user_readenv=1这个配置确实容易忽略,之前测试环境就因为这个被提权了
远程SSH开allow_active?这配置也太不小心了吧🤔
问下这种问题一般怎么排查,审计日志有啥特征吗