叹号!禁用命令高危参数的核心是显式排除危险参数组合,而非过滤参数内容;必须将!规则与白名单置于同一授权行,如alice all=(root) nopasswd: safe, !/usr/bin/python3 -c *, !/bin/bash,单独写或混入别名均无效。

在 sudoers 中用叹号 ! 禁用特定命令的高危参数,核心不是“过滤参数内容”,而是**在命令白名单中显式排除危险参数组合**。sudo 不解析命令内部字符串(比如 python3 -c "..." 里的引号内代码),但它会按完整命令行匹配——所以必须把带危险参数的整条调用写成否定项,并与授权命令放在同一行。
叹号必须和白名单共存于同一授权行
单独写 alice ALL=(root) !/usr/bin/python3 -c * 是无效的。否定只在具体授权上下文中起作用:
- ✅ 正确写法:
alice ALL=(root) NOPASSWD: /usr/bin/journalctl, !/usr/bin/python3 -c *, !/bin/bash, !/usr/bin/less - ❌ 错误写法:
alice ALL=(root) !/usr/bin/python3 -c *(无主授权,不生效) - ❌ 错误写法:
Cmnd_Alias DANGEROUS = !/bin/sh(别名里不能用 !,语法非法)
禁用高危参数组合的关键模式
常见需否定的参数组合,本质是能触发子 shell、代码执行或任意文件读取的调用方式:
-
!/usr/bin/python3 -c *:防os.system("sh")或__import__加载任意模块 -
!/usr/bin/perl -e *和!/usr/bin/ruby -e *:同理,解释器 + 执行参数 = 逃逸通道 -
!/usr/bin/find * -exec /bin/sh \;:防止 find 调用 shell,注意*匹配任意起始路径 -
!/usr/bin/awk 'BEGIN {system("")}':单引号内含 system() 调用,需完整匹配字符串(sudo 支持简单字面匹配) -
!/usr/bin/less:虽无参数也禁,因运行中按!或v可直接启 shell
参数通配符 * 的使用边界
* 在 sudoers 中仅作“剩余参数占位符”,不能用于路径段,且只匹配非空参数:
- ✅
/usr/bin/systemctl restart *:允许restart nginx、restart docker,但不匹配restart(无参数) - ✅
!/bin/sh -c *:覆盖-c "id"、-c '/bin/bash'等所有 -c 形式 - ❌
/usr/bin/*:非法,sudo 拒绝通配符在路径中出现 - ⚠️ 注意:空格敏感,
!/usr/bin/python3 -c*(中间无空格)不会匹配-c "...",必须写成-c *
验证否定是否真正生效
改完配置后,必须以目标用户身份实测,不能只看语法:
- 运行
sudo -l:输出中应明确列出类似(root) !/usr/bin/python3 -c *, !/bin/bash的拒绝项 - 手动触发:
sudo /usr/bin/python3 -c "import os; os.system('/bin/sh')"→ 应报错command not allowed - 检查日志:
sudo grep 'python3.*-c' /var/log/auth.log,确认有拒绝记录而非静默失败 - 对
sudo /usr/bin/less /etc/shadow按!后输sh,应被中断退出,不进入 shell











