默认 sudo 配置不等于安全,因 %wheel ALL=(ALL) NOPASSWD: ALL 等宽松策略易被滥用;需最小化授权、限定命令路径、启用日志审计与 seccomp-bpf 等深度防护措施。

为什么默认的 sudo 配置不等于安全
很多管理员以为只要开了 sudo、禁了 root 登录,系统就算“加固”了。实际上,/etc/sudoers 里一行 %wheel ALL=(ALL) NOPASSWD: ALL 就足以让任意 wheel 成员绕过所有命令级约束,执行 sudo setcap 'cap_net_bind_service+ep' /usr/bin/python3 后直接监听 80 端口——这和拥有 root 权限几乎无异。
真正需要做的是最小化授权:
- 用
visudo -f /etc/sudoers.d/app-deploy拆分策略,避免主文件被误改 - 显式限定命令路径:
deployer ALL=(www-data) /usr/bin/systemctl start nginx,禁用通配符和 shell 元字符 - 加
requiretty和env_reset,防止伪终端逃逸和环境变量污染 - 启用
sudo_logfile并轮转日志,否则攻击者删掉/var/log/sudo.log就没痕迹
seccomp-bpf 不是容器专属,普通服务也能用
很多人只在 Docker 的 --security-opt seccomp=... 里见过 seccomp-bpf,但 systemd 从 v245 起就支持为任意 service 单独加载过滤器。比如运行一个只读配置解析器,完全不需要 openat 以外的文件操作,更不该调用 execve 或 socket。
实操步骤:
- 用
libseccomp工具生成策略:scmp_bpf_compile -m 2 -o nginx-seccomp.bpf nginx-seccomp.json - 在 service 文件中添加:
SystemCallFilter=@system-service @file-system ~@privileged ~@mount - 注意:
@system-service是白名单组,不是通配符;漏掉clock_gettime或getrandom可能导致进程启动失败 - 测试时先加
SystemCallErrorNumber=EPERM,避免直接 kill 进程,方便抓 syscall 日志
SSH 登录后第一件事不是改密码,而是查 ~/.ssh/authorized_keys 和 PAM 模块链
入侵者很少暴力破解密码,更多是复用已有密钥或通过 PAM 模块注入。一次看似正常的登录,背后可能是 auth [success=done] pam_exec.so /usr/local/bin/pam-backdoor.sh 在静默执行。
应立即检查:
-
grep -r "pam_exec\|pam_python" /etc/pam.d/—— 非标准模块需人工审计 -
ssh-keygen -l -f ~/.ssh/authorized_keys查看密钥指纹,比对上次备份 -
systemctl show sshd | grep -i "pam\|permit"确认未启用PermitRootLogin yes或PasswordAuthentication yes - 检查
/etc/ssh/sshd_config中的AuthorizedKeysCommand,它可能动态拉取远程密钥列表
日志不是存着就行,journald 默认配置会丢关键事件
journalctl --since "2 hours ago" 查不到东西?大概率是 Storage=volatile(默认值),所有日志只存在内存里,重启即清空。更隐蔽的问题是 RateLimitIntervalSec 和 RateLimitBurst 过严,导致暴力破解尝试被合并成一条 “Failed password for user”,掩盖真实攻击频次。
必须调整的几项:
- 编辑
/etc/systemd/journald.conf,设Storage=persistent并确认/var/log/journal/目录存在且属root:systemd-journal - 加大速率限制:
RateLimitIntervalSec=30s,RateLimitBurst=10000,避免漏记高频登录失败 - 启用字段过滤:
ForwardToSyslog=yes+ rsyslog 转发到远程服务器,本地日志仍可被删,远程不可逆 - 定期用
journalctl --verify检查日志完整性,返回非零码说明有篡改或损坏
长期防护不是堆工具,是持续验证每个环节是否真在生效——比如改完 sudoers 后,立刻用受限用户跑一遍预期命令;加了 seccomp 就用 strace -e trace=all 看实际调用是否被拦截;连上 SSH 后第一行命令永远是 sudo journalctl -n 20 --no-pager,而不是急着改配置。










