核心是收窄sudo切换行为:在sudoers中前置禁止shell类命令(如!/bin/bash、!/usr/bin/sudo -u root *)和高危账号调用,再通过Cmnd_Alias白名单授权具体运维动作(如systemctl控制服务),并配合setfacl封禁shell执行及设置nologin shell实现纵深防御。

限制管理员通过 sudo 切换到高危系统账号(如 root、mysql、postgres、redis 等),核心不是“禁止 sudo”,而是**收窄切换行为本身**:禁止执行 sudo su -、sudo -i、sudo -u xxx /bin/bash 等通用提权入口,同时对确需的特定操作做白名单授权。
1. 在 sudoers 中显式禁止 shell 切换类命令
这是最直接有效的控制层。必须用绝对路径 + 明确参数模式,并确保规则位于通用授权行之前:
- 在
/etc/sudoers或/etc/sudoers.d/下添加(用visudo编辑):
adminuser ALL=(ALL) !/bin/su, !/bin/su -, !/usr/bin/su, !/usr/bin/su -, \
!/bin/bash, !/bin/sh, !/usr/bin/bash, !/usr/bin/sh, \
!/usr/bin/sudo -i, !/usr/bin/sudo -s, !/usr/bin/sudo -u *, /bin/bash, \
!/usr/bin/sudo -u *, /bin/sh注意:! 后必须是完整匹配路径+参数组合;-u * 是通配符禁止,防止绕过指定用户;多行用 \ 续行。
2. 封禁对高危系统账号的直接 sudo -u 调用
即使不禁止 shell,也要阻断以系统账号身份运行任意命令的行为:
- 添加更细粒度拒绝规则(同样放于通用规则前):
adminuser ALL=(ALL) !/usr/bin/sudo -u root *, \
!/usr/bin/sudo -u mysql *, !/usr/bin/sudo -u postgres *, \
!/usr/bin/sudo -u redis *这样 sudo -u mysql mysql -e "DROP DATABASE ..." 会被拒绝,但 sudo systemctl restart mysql(若已白名单)仍可执行。
3. 替代方案:只授权具体运维动作,不开放账号切换
真正安全的做法是消除“切换账号”需求,改为授权原子化操作:
- 定义命令别名,仅允许必要动作:
Cmnd_Alias MYSQL_ADMIN = /usr/bin/systemctl start mysqld, \
/usr/bin/systemctl stop mysqld, /usr/bin/mysqladmin ping, \
/usr/bin/mysqldump --single-transaction --databases *- 绑定权限(不带
NOPASSWD更稳妥):
adminuser ALL=(root) MYSQL_ADMIN
用户只能执行数据库服务启停、健康检查、备份等明确动作,无法获得 mysql 用户 shell 或任意 SQL 执行权。
4. 配合 PAM 和文件权限加固防绕过
仅靠 sudoers 不够,还需切断本地直连路径:
- 用
setfacl封死系统账号对应 shell 的执行权限(例如禁止普通用户执行/bin/bash): sudo setfacl -m u:adminuser:--- /bin/bashsudo setfacl -m u:adminuser:--- /bin/sh- 确认
/etc/passwd中高危账号的 shell 字段为/sbin/nologin或/usr/sbin/nologin,避免被sudo -u xxx /bin/bash强行调用
这些措施共同构成纵深防御:sudoers 控制命令入口,ACL 封堵二进制直连,PAM 和 passwd 确保账号本身不可交互登录。


















