auditctl -w 监控证书目录必须用绝对路径且禁用通配符,因-auditd仅支持对已存在绝对路径做inotify式监控,不解析shell通配符、不递归子目录;需聚焦/etc/ssl/private等高风险目录,用-p wa监控写与属性变更,并结合exit=-13捕获失败读取,永久规则须存入/etc/audit/rules.d/并chmod 600后augenrules --load加载。

auditctl -w 监控证书目录时为什么必须用绝对路径且禁止通配符
因为 auditd 的 -w 规则只支持对**已存在**的绝对路径做 inotify-style 监控,不解析 shell 通配符(如 /etc/ssl/certs/*.pem),也不递归子目录。你写 auditctl -w /etc/ssl/certs -p r -k cert_read,它只会监控该目录本身的 open/openat 系统调用,而不会捕获对其中任意 .crt 或 .key 文件的读取——除非你显式监控每个文件或其父目录的“属性变更+写”事件。
真正有效的做法是:聚焦高风险路径,例如:
-
/etc/ssl/private/(私钥集中存放,默认应为 700 权限) -
/etc/pki/tls/private/(RHEL/CentOS 系统常用) -
/var/lib/kubelet/pki/(Kubernetes 节点证书)
对这些目录使用 -p wa(写 + 属性修改),而非 -p r;因为非授权访问往往伴随权限提升、文件复制或重命名等操作,单纯 r 很难触发且日志爆炸。
如何用 -p wa 捕获“读取私钥”的间接行为而非直接 -p r
攻击者极少直接 cat /etc/ssl/private/server.key——那样会留下明显痕迹。更常见的是:cp 复制到临时目录、openssl rsa -in ... 解析、或通过 systemd 服务配置把私钥路径注入到进程环境。这些动作都会触发目标文件的 open(O_RDONLY) 或 stat(),但 auditd 默认不记录 stat;而 cp 和 openssl 启动时会对私钥文件执行 openat(AT_FDCWD, "...", O_RDONLY),这属于“读”操作,但仅当目录被 -p r 监控时才生效——而你又不该开 -p r。
绕过这个限制的实战方案是:监控私钥所在目录的 -p wa,再结合 aureport -f --start today 查看所有失败的文件访问(success=no)。非授权用户尝试读私钥时,内核会返回 EACCES,auditd 仍会记录该 open 系统调用及其 exit=-13(拒绝访问)。所以关键不是“抓到读”,而是“抓到失败的读”。
示例规则:
sudo auditctl -w /etc/ssl/private/ -p wa -k ssl_private_access
后续查异常访问:
sudo ausearch -k ssl_private_access -m open,openat -i | grep "exit=-13"
永久规则必须写进 /etc/audit/rules.d/ 且 chmod 600
临时规则(auditctl 添加)在 reboot 或 auditd 重启后全部丢失。生产环境必须用永久规则。规则文件名需以 .rules 结尾,例如 /etc/audit/rules.d/ssl.rules,内容格式严格:
-w /etc/ssl/private/ -p wa -k ssl_private_access -w /etc/pki/tls/private/ -p wa -k pki_private_access
注意:
- 每行一条规则,末尾不能有空格或注释
- 必须用
sudo chmod 600 /etc/audit/rules.d/ssl.rules,否则augenrules拒绝加载(auditd 安全策略强制) - 加载命令是
sudo augenrules --load,不是systemctl restart auditd(后者在 CentOS 7 中会导致规则清空)
验证是否生效:sudo auditctl -l | grep ssl_private_access
日志分析时别漏掉 auid 和 exe 字段
一个典型的私钥访问事件里,uid 可能是 root(因为服务以 root 运行),但真正登录并触发该操作的人是 auid(audit uid),即最初登录用户的 UID。这是区分“合法运维”和“横向移动”的唯一可靠依据。
同时,exe 字段显示实际执行程序的绝对路径(如 /usr/bin/openssl),比 comm(进程名)更防伪造。例如:
type=SYSCALL msg=audit(1745732982.123:45678): arch=c000003e syscall=257 success=no exit=-13 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=3 comm="openssl" exe="/usr/bin/openssl" key="ssl_private_access"
这里 auid=1001 表示普通用户账号发起,exe="/usr/bin/openssl" 暴露了工具链,exit=-13 确认是权限拒绝——三者叠加才能判定为可疑非授权访问尝试。
真正容易被忽略的点是:auditd 不会自动关联父子进程。如果某个脚本启动了 openssl,你得靠 ausearch -p 45678(用上例中的事件 ID)向上追溯完整调用链,否则可能把 root cron job 误判为入侵。


















