最稳妥的服务账号锁定方式是先用passwd -l锁定密码字段,再将shell设为/sbin/nologin(RHEL/CentOS)或/usr/sbin/nologin(Debian/Ubuntu),并清理crontab及残留进程;/bin/false因返回非零状态码可能引发老旧服务异常,应避免使用。

要对 /etc/passwd 中的服务账号 Shell 路径做精细裁剪,核心目标不是简单“删掉”或“乱填”,而是精准切断其交互式执行能力,同时保留系统服务正常运行所需的身份上下文。关键在于区分“禁止登录”和“禁止执行任意命令”——很多服务账号(如 www-data、mysql、apache)本就不该有 shell,但必须能被服务进程以该 UID 启动。
只改 Shell 不等于禁用账号
直接把服务账号的 shell 改成 /bin/false 或 /usr/sbin/nologin 是常见做法,但要注意:
-
/bin/false会立即退出并返回非零状态码,某些老旧服务(如 sendmail、postfix)可能误判为异常,导致日志刷屏或服务启动失败 -
/usr/sbin/nologin(Debian/Ubuntu)或/sbin/nologin(RHEL/CentOS)更稳妥,它会输出提示语(可自定义/etc/nologin.txt),且返回 0 状态码,兼容性更好 - 仅改 shell 无法阻止 SSH 密钥免密登录后执行命令(如
ssh user@host 'id'),也不能拦住 crontab 或 systemd timer 触发的任务
真正生效的密码字段锁定才是根基
Linux 认证流程中,shell 是登录成功后的产物;而认证本身由 /etc/shadow 控制。所以首要操作是锁密码:
- 运行 sudo passwd -l username:在
/etc/shadow对应行密码字段前加!(如!$6$abc...),让 PAM 直接拒绝所有基于密码的认证 - 验证是否生效:查看
sudo getent shadow username,确认开头是单个!,不是!!(后者可能是重复锁定或异常) - 注意:
passwd -l不影响已存在的会话,也不拦 root 执行su - username—— 若需彻底限制,必须配合 shell 修改
配套清理定时任务与服务残留
服务账号常自带 crontab 或 systemd 用户级服务,这些不依赖 shell 登录也能运行:
- 清空用户级定时任务:sudo crontab -e -u username → 保存空文件,或直接 sudo rm /var/spool/cron/username(路径因发行版而异)
- 禁用用户级 systemd 服务:sudo systemctl --user --machine=username@.service disable 不适用,应查 sudo loginctl list-users 和 sudo systemctl --user list-units --type=service --all -u username
- 检查是否存在遗留的守护进程:ps -u username,确认无非预期长期运行进程
验证与审计要点
执行完上述操作后,不能只看命令返回成功,要实测几类典型访问路径:
- SSH 密码登录 → 应失败(PAM 拒绝)
- SSH 密钥登录 → 应失败(若 shell 是 nologin)或进入后立即退出(若 shell 是 false)
-
su - username→ 若 shell 已设为 nologin,则被拦截;若未设,则仍可切换(此时需依赖passwd -l防止后续 su 过程中的密码验证) -
sudo -u username bash -c 'id'→ 仍可执行,这是设计使然(服务调用需要),不属于漏洞;如需限制,应通过 sudoers 白名单或 SELinux 策略控制具体命令

















