应监控触发历史记录行为的底层系统调用而非~/.bash_history文件,如execve、openat、unlinkat等,并通过auditd规则捕获shell执行、库加载、ssh密钥修改及历史清空尝试,辅以bash内建命令日志增强审计能力。

直接监控“命令执行历史”本身(比如 ~/.bash_history)在 auditd 中不可靠,因为该文件路径分散、行为复杂、易绕过,且 auditd 的 -w 规则无法稳定覆盖动态用户目录。真正有效的做法是监控触发历史记录行为的底层动作和关键系统调用,从攻击链源头切入。
聚焦高危命令执行过程,而非结果文件
auditd 的优势在于捕获内核级系统调用,如 execve(执行程序)、openat(打开文件)、unlinkat(删除文件)等。篡改或清除历史的本质目的,是掩盖操作痕迹——所以应监控那些“可能用于隐藏、伪造或绕过审计”的动作。
锁定关键可执行文件与敏感路径
攻击者常通过替换或劫持 shell 二进制、注入共享库来规避日志。以下规则能捕获这类前置行为:
- 监控
/bin/bash、/usr/bin/sh被执行:auditctl -w /bin/bash -p x -k shell_exec - 监控 libc 等核心库被加载(防 LD_PRELOAD 注入):
auditctl -w /usr/lib64/libc.so.6 -p r -k libc_load - 监控 SSH 密钥文件变动(攻击者常删 key 或加后门):
auditctl -w /root/.ssh/authorized_keys -p wa -k ssh_key_mod
捕获清空/覆盖历史的典型系统调用
不依赖路径匹配 .bash_history,而是抓取实际执行清空动作的系统调用:
- 记录所有
execve调用,并标记 shell 启动事件:auditctl -a always,exit -F arch=b64 -S execve -F exe=/bin/bash -F key=shell_spawn - 捕获对常见历史路径的删除尝试(模糊匹配,兼容不同用户名):
auditctl -a always,exit -F arch=b64 -S unlinkat -F path=.bash_history -F key=history_wipe_attempt
注意:path=是字符串匹配,不是 inode 绑定,适合此类场景;后续用ausearch -k history_wipe_attempt -i查看完整上下文。
启用 shell 内建命令日志(最直接补充)
auditd 不解析命令语义,但 bash 可主动上报。在 /etc/bash.bashrc 中添加:export PROMPT_COMMAND='logger -p local6.info "$(whoami) [$$] $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//") [$?]"'
再配置 rsyslog 将 local6.* 写入独立日志文件(如 /var/log/shell-commands.log),即可获得可读性强、时间准、含返回码的操作记录。
让规则持久化并验证生效
临时规则重启即丢,必须落盘:
- 将上述
auditctl -w和-a规则分别写入/etc/audit/rules.d/shell.rules和/etc/audit/rules.d/history.rules(文件名必须以.rules结尾) - 执行
sudo augenrules --load加载 - 验证:
sudo auditctl -l | grep -E "(shell_exec|history_wipe)"应显示对应规则
查日志时务必加 -i(还原用户/命令名)和 -k(精准过滤):sudo ausearch -k shell_spawn -m SYSCALL -i --start today | grep -E "(comm=|exe=|uid=|cwd=)"
不复杂但容易忽略











