需结合 auditd 规则、execve 事件捕获、auditctl 监控及日志解析:1. 启用 execve 参数记录并配置双架构规则;2. 通过 sudo 和 shell 路径规则+ auid 过滤聚焦交互式会话;3. 关联 execve 与 exit 事件提取命令及 exit= 字段退出码;4. 建议启用 sudo log_output、iolog_dir 并限制权限。

要记录所有通过 sudo 启动的交互式 shell(如 sudo -i、sudo bash、sudo su -)所执行的每条命令及其退出状态码,仅靠默认的 auditd 配置是不够的——它默认不跟踪子进程的命令行参数和退出码。需结合 auditd 规则、execve 事件捕获、auditctl 实时监控,并辅以合理的日志解析逻辑才能实现目标。
1. 确保 auditd 正常运行并启用 execve 记录
auditd 默认会记录 execve 系统调用,但部分发行版(如 RHEL/CentOS 8+、Ubuntu 20.04+)为减少开销,默认禁用了对命令行参数(argc/argv)的完整记录。需确认并启用:
- 检查当前是否记录参数:
auditctl -s | grep "enabled\|argv";若输出含argv=0,说明未记录参数 - 编辑
/etc/audit/rules.d/audit.rules,确保包含:-a always,exit -F arch=b64 -S execve -k sudo_cmd-a always,exit -F arch=b32 -S execve -k sudo_cmd
(双架构适配,x86_64 系统建议保留两者) - 重启服务生效:
sudo systemctl restart auditd
2. 精准匹配 sudo 启动的交互式 Shell 进程链
单纯记录所有 execve 事件会产生海量日志。关键在于识别“由 sudo 启动的 shell 及其子命令”。审计规则本身无法直接匹配进程树,但可通过以下方式聚焦:
- 添加针对
sudo自身的 execve 记录,用于定位起点:-a always,exit -F path=/usr/bin/sudo -F perm=x -k sudo_exec - 对常见交互式 shell 添加规则(覆盖主流路径):
-a always,exit -F path=/bin/bash -F perm=x -k sudo_shell-a always,exit -F path=/bin/sh -F perm=x -k sudo_shell-a always,exit -F path=/bin/zsh -F perm=x -k sudo_shell-a always,exit -F path=/usr/bin/bash -F perm=x -k sudo_shell - 重要:这些规则必须配合
-F auid!=unset(或-F auid>=1000)过滤掉系统服务调用,只保留真实用户行为
3. 解析日志获取命令与退出状态码
auditd 的 execve 事件本身不直接记录退出状态码。退出码需从后续的 exit 或 exit_group 系统调用中提取,并与对应进程 ID(pid)和线程 ID(tid)关联。操作步骤如下:
- 使用
ausearch -m execve,exit,exit_group -ts recent -k sudo_cmd获取近时段相关事件 - 按
pid和tid分组,找出同一 shell 会话下的命令序列(execve)与最终退出(exit)事件 - 在
exit事件中查找exit=字段,即该进程的退出状态码(例如exit=0表示成功) - 推荐用
aureport --start recent --key sudo_cmd --format csv导出结构化数据,再用脚本(如 awk / Python)做 pid 关联解析
4. 补充建议:增强可审计性与实用性
纯 auditd 方案存在解析复杂、性能开销大等问题。生产环境建议组合使用:
- 启用
sudo自身的日志功能:
在/etc/sudoers中设置Defaults log_output和Defaults iolog_dir="/var/log/sudo-io/%{user},可录制完整终端会话(含命令+输出+退出码),但需搭配script工具支持 - 限制交互式 sudo 权限:避免泛授权
ALL=(ALL) ALL,改用ALL=(ALL) /bin/bash, /bin/sh, /usr/bin/zsh等显式白名单,缩小审计范围 - 定期归档与压缩 audit 日志:
/etc/audit/auditd.conf中配置max_log_file_action = rotate和num_logs = 10,防止磁盘占满











