auditd本身不区分授权与否,需通过规则设计+日志过滤识别非授权访问:核心依据是auid≠0和exit=-13,而非单纯监控读操作;永久规则须写入/etc/audit/rules.d/并augenrules --load加载。

auditd 本身不区分“授权”或“非授权”,它只记录谁、何时、以何种系统调用方式访问了 /etc/shadow;所谓“非授权访问”,必须靠规则设计 + 日志过滤 + 上下文判断来识别——核心是盯住 auid!=0 和 exit=-13 这两个信号。
为什么不能只加 -p r 监控读操作
单纯写 auditctl -w /etc/shadow -p r -k shadow_read 会捕获所有读,包括 root 自己的合法操作(如 passwd、usermod),日志爆炸且无区分度。更关键的是:普通用户执行 cat /etc/shadow 时,内核直接拒绝(open() 返回 -EACCES),auditd 仍会记录该系统调用,但 exit 字段为 -13,而非 0。这个失败信号才是非授权访问的实质证据。
- 必须配合
-m SYSCALL查open/openat事件,不能只查file类型 -
-p r在某些内核版本中对/etc/shadow可能不触发(因权限检查早于 open 调用),而exit=-13总会出现 - 别依赖
comm=判断工具名——攻击者可用python3 -c "open('/etc/shadow')"绕过简单匹配
怎么写真正有效的永久规则
临时规则重启即丢,生产环境必须固化到 /etc/audit/rules.d/ 并重载。针对非授权访问,推荐两条互补规则:
-
-w /etc/shadow -p wa -k shadow_access:监控写和属性变更(防篡改、防 chown/chmod) -
-a always,exit -F path=/etc/shadow -F perm=r -F auid!=0 -k unauthorized_shadow_read:聚焦原始登录用户非 root 的读意图(auid是登录会话起始 UID,比uid更可靠)
把它们写进 /etc/audit/rules.d/10-shadow.rules,然后运行:sudo chmod 600 /etc/audit/rules.d/10-shadow.rulessudo augenrules --load
验证是否加载:sudo auditctl -l | grep unauthorized_shadow_read
如何快速确认某次访问是非授权的
加完规则后,立即模拟测试(普通用户下):su -c "cat /etc/shadow" -l testuser 2>/dev/null || true,再执行:
- 查失败读取:
sudo ausearch -k unauthorized_shadow_read -m open,openat -i --start recent | grep "exit=-13" - 看是谁发起的:
sudo ausearch -k unauthorized_shadow_read -m open,openat -i --start recent | grep "auid="(非 0 才可疑) - 排除 root 误报:
sudo ausearch -k unauthorized_shadow_read -m open,openat -i --start recent | grep -v "auid=0"
注意:ausearch 默认查 /var/log/audit/audit.log,若日志轮转过,需加 --start today 或指定文件路径。
容易被忽略的关键点
很多团队卡在“规则写了但没日志”,问题往往出在:
— auditd 没真在跑:systemctl status auditd 必须显示 active (running),不是 inactive 或 failed
— 内核模块没加载:lsmod | grep audit 应有输出,否则 sudo modprobe audit
— 规则路径写错:ls -i /etc/shadow 确认真实 inode 路径,避免监控软链接目标之外的路径
— enabled 关闭了:sudo auditctl -s | grep enabled 输出必须是 enabled 1,否则整个审计链路静默失效


















