要封锁高权限运维人员通过sudo间接获取root shell,必须用Cmnd_Alias集中定义并全局排除高危命令(如/bin/bash、/bin/su、python3 -c等),配合Defaults noexec、requiretty、禁用ALL授权及sudo -l实测验证,实现白名单+黑名单双重控制。

要封锁高权限运维人员通过 sudo 间接获取真实 root shell(比如执行 /bin/su -、/bin/bash 或 sudo -i),不能靠“信任人”,而要靠“堵住所有已知逃逸路径”。Sudoers 的命令别名排除机制(! 前缀)是其中关键一环,但必须配合其他硬性约束才真正有效。
一、用 Cmnd_Alias 显式定义禁止命令集,再全局排除
单纯在授权行里写 ! 容易遗漏或被绕过。更稳妥的做法是:先集中定义一组公认的高危命令,再对目标用户或组统一禁用。
# /etc/sudoers 或 /etc/sudoers.d/90-block-escape
Cmnd_Alias ESCAPE_CMDS = \
/bin/sh, /bin/bash, /bin/zsh, /bin/dash, \
/usr/bin/sh, /usr/bin/bash, /usr/bin/zsh, \
/bin/su, /usr/bin/su, \
/usr/bin/python3 -c *, /usr/bin/perl -e *, /usr/bin/ruby -e *, \
/usr/bin/find * -exec sh \;, /usr/bin/awk 'BEGIN {system("")}', \
/bin/systemctl edit *, /bin/systemctl --no-pager * exec *然后对运维组(如 %ops)做「白名单 + 黑名单」双重控制:
%ops ALL=(root) NOPASSWD: SVC_CTRL, LOG_VIEW, RESTART_SERVICES %ops ALL=(ALL) !ESCAPE_CMDS
✅ 这表示:只允许执行
SVC_CTRL等已定义的白名单命令;同时明确禁止执行ESCAPE_CMDS中任意一条——即使某条命令意外落在白名单之外,也会被第二行拦截。
二、禁用 sudo -i、sudo -s 和 shell 启动类参数
仅禁路径还不够,sudo 自身的子命令也能启动交互 shell。需在 Defaults 区域加固:
# 加在 /etc/sudoers 文件顶部(visudo 打开后第一段) Defaults requiretty Defaults !authenticate Defaults !env_reset Defaults env_delete -= "PATH" Defaults env_check += "TERM" Defaults noexec # ⚠️ 关键!阻止 exec 类逃逸(需确认业务无依赖) Defaults !use_pty # 可选,防伪终端绕过
特别注意:
-
noexec会禁用less、man、vi等调用子进程的命令,若需保留,可改用Defaults !noexec+ 显式禁用!/usr/bin/less等具体命令 -
requiretty强制要求操作必须来自真实终端,阻断 cron、webshell 等非交互提权场景
三、禁止以 root 身份执行任意命令的“兜底权限”
很多团队误以为给 NOPASSWD: ALL 再加 !ESCAPE_CMDS 就安全了,其实不成立——ALL 本身包含大量可组合利用的命令(如 cp /etc/shadow /tmp && chmod 777 /tmp/shadow)。
✅ 正确做法是:彻底删除 ALL 授权,只留明确路径+固定参数的命令。例如:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
# ❌ 危险(即使加了 !ESCAPE_CMDS,仍可能被利用)
%ops ALL=(root) NOPASSWD: ALL, !ESCAPE_CMDS
# ✅ 安全(只开放必要动作,无例外)
%ops ALL=(root) NOPASSWD: \
/bin/systemctl start nginx, \
/bin/systemctl stop nginx, \
/usr/bin/journalctl -u nginx.service -n 100, \
/usr/bin/tail -n 50 /var/log/nginx/error.log? 提示:用
sudo -l -U opsuser检查该用户实际能跑什么,输出中不应出现ALL、/bin/bash、/bin/sh、/bin/su或任何带-c、-e、exec的命令
四、验证是否真被封死:三步实测法
配置完别急着上线,立即用目标用户账号测试:
-
试逃逸入口
sudo /bin/bash sudo /bin/sh sudo /usr/bin/python3 -c 'import os; os.system("/bin/bash")' sudo -i sudo -s -
试参数注入绕过
sudo /bin/systemctl restart nginx; /bin/bash # 分号注入 sudo /bin/systemctl restart 'nginx; /bin/sh' # 引号绕过(若未加固参数解析)
-
试日志/编辑类命令逃逸
sudo /usr/bin/less /var/log/auth.log # less 内按 !sh sudo /usr/bin/vi /dev/null # vi 内 :!sh
只要任一成功,说明策略有缺口,需回退检查 noexec、env_delete、命令路径完整性及 Cmnd_Alias 是否覆盖全面。
不复杂但容易忽略。核心就四点:别名禁用高危命令、关闭 shell 启动能力、拒绝 ALL 授权、每次修改后实测逃逸路径。

















