可通过PAM的pam_shells模块结合/etc/shells白名单实现基础shell限制,再用pam_listfile或pam_exec对特定用户或组实施细粒度策略,但需注意服务独立配置、shell字段合理设置及登录后行为管控。

可以通过 PAM(Pluggable Authentication Modules)的 pam_shells 模块配合系统 shell 白名单,结合 pam_listfile 或自定义规则,实现对特定用户的 shell 限制。核心思路是:不让用户登录时切换到非授权 shell,而非仅修改其 /etc/passwd 中的 shell 字段(该字段易被绕过或误改)。
配置 pam_shells 实现基础 shell 白名单校验
pam_shells 是 PAM 自带模块,用于检查用户登录时指定的 shell 是否存在于 /etc/shells 中。它默认在 auth 或 account 堆栈中启用(如 /etc/pam.d/sshd 或 /etc/pam.d/login)。要使其生效:
- 确保目标用户的
/etc/passwd中 shell 字段为合法路径(如/bin/bash),否则登录会直接失败 - 将允许使用的 shell 显式写入
/etc/shells,每行一个(例如:/bin/bash、/usr/bin/zsh、/bin/false) - 确认对应服务的 PAM 配置中包含类似行:
auth [success=ok default=die] pam_shells.so或account required pam_shells.so
用 pam_listfile 限制特定用户只能使用指定 shell
若需更细粒度控制(例如:只允许 userA 用 /bin/bash,userB 只能用 /usr/bin/rbash),可借助 pam_listfile 模块做账户级判断:
- 创建映射文件,如
/etc/security/shell_map,格式为:username:/path/to/allowed/shell - 在
/etc/pam.d/sshd(或其他登录服务)中添加:auth [success=ok default=bad] pam_listfile.so item=user sense=allow file=/etc/security/shell_map onerr=fail - 再加一行校验 shell 是否匹配:
auth [success=ok default=bad] pam_exec.so /usr/local/bin/check-user-shell(需自行编写脚本读取环境变量PAM_USER和PAM_SERVICE,比对当前会话请求的 shell 是否与映射文件一致)
结合 pam_exec 实现动态 shell 策略
对于复杂策略(如按组、时间、来源 IP 限制 shell),pam_exec 更灵活。例如限制某用户组只能使用受限 shell:
- 编写校验脚本
/usr/local/bin/restricted-shell-check,检查$PAM_USER是否属于restricted_users组,并验证$SHELL是否为/bin/rbash或/usr/sbin/nologin - 在
/etc/pam.d/sshd中插入:auth [success=ok default=bad] pam_exec.so /usr/local/bin/restricted-shell-check - 注意:脚本需有执行权限,且避免输出干扰 PAM 流程;返回值 0 表示通过,非 0 则拒绝
注意事项与常见陷阱
实际部署时容易忽略以下几点:
- 服务 PAM 配置优先级:不同服务(sshd、su、login)使用独立的 PAM 配置文件,需分别修改
-
shell 字段仍需合理设置:即使 PAM 限制了登录时可用 shell,用户若已有交互式会话,仍可能通过
exec或chsh切换——应同时禁用chsh权限或限制其可选 shell -
调试建议:启用
pam_echo或在脚本中写日志(如logger "pam check for $PAM_USER"),配合journalctl -u sshd查看认证日志 - 安全边界:PAM 控制的是“登录阶段”,无法阻止已登录用户执行任意二进制。真正隔离需配合容器、seccomp 或 SELinux 等机制

















