← 中文资源

简体中文版本

审查 sudoers 提权路径

导出每个用户生效的 sudo 规则,清查越界的通配符与 NOPASSWD 授权,用参数钉死收紧命令。

阅读英文原文

目标

sudoers 规则的失败是安静的:它一直“正常工作”,却悄悄授予远超意图的权限。它的通配符语义与 shell glob 不同,会跨空格匹配参数,/opt/app/bin/* 实际也匹配“脚本 + 任意参数”的组合。按用户导出生效规则、亲手演示越权路径、再改写成钉死参数的命令,把模糊的加固清单变成具体修复,并用审计日志收尾。

步骤要点

  1. 用 sudo -l -U deploy 导出该账号生效的规则,注意 NOPASSWD 标记与通配符参数。
  2. 在 /etc/sudoers.d/ 里找到源规则行,找出授予整个目录任意二进制执行权的写法。
  3. 对被授权目录做 find -perm -o+w,列出可写文件;通配符规则下任何一个都是任意 root 代码入口。
  4. 用 visudo 把规则改写成钉死命令与固定参数的形式,比如只允许 systemctl restart app.service 与带固定日志路径的轮转命令。
  5. 重跑 sudo -l 验证收紧生效,实际执行一次被允许的命令,并在 journalctl 里确认 sudo 审计事件完整记录。

排错提示

sudoers 通配符跨空格匹配,/opt/app/bin/* 也会匹配“脚本加任意参数”,命令路径别用通配符、参数要显式钉死;直接编辑 sudoers 文件可能弄坏 sudo,务必用 visudo 解析后再保存,锁死时用恢复模式还原;钉死的脚本本身可写就前功尽弃,确保脚本与目录 root 所有且非组可写,或改调编译好的二进制。

适用边界

sudo -l 只反映检查时刻的策略,组归属或 LDAP 规则变化都会改写它,需要周期性复审;NOPASSWD 拿交互性换暴露面,只在自动化确实无法提供凭据的场景保留。

代码示例

# What can deploy actually do as root?
sudo -l -U deploy
# (root) NOPASSWD: /opt/app/bin/*

# Wildcards match across spaces in sudoers:
# /opt/app/bin/*  ALSO matches
#   /opt/app/bin/rotate-logs /etc/shadow   <-- escalation

# ls the granted directory for writable files
find /opt/app/bin -perm -o+w -type f
# /opt/app/bin/dev-helper.sh   (world-writable = root shell)

# Pin it down (visudo -f /etc/sudoers.d/deploy)
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app.service