分清哪些留得下、哪些留不下
本实验在 VM 中运行
一台 Ubuntu 24.04 VM。以 root 身份运行并拥有内核权限,所以可以真正加载审计规则。实验 Pod 中没有任何 capability,auditctl 根本无法工作,所以只有本实验在 VM 中运行。首次启动需要 1–2 分钟。
目标
亲手设置内核审计规则,故意制造事件,并取出记录来阅读。在 journal 一侧重新找到同一个事件,查看两份记录各自包含什么,最后找出没有被监视的位置并把它覆盖起来。
为什么重要
在编写检测规则之前,有一个必须回答的问题——这个事件最初有没有被记录在某个地方。在 Linux 上,内核审计默认几乎什么也不记录。它只看设置了规则的路径和系统调用。所以才会出现“日志都收集了,却没有答案”的情况。
这里要学的不是命令,而是范围感。如果能说清自己的规则看什么、不看什么,事件发生时就能区分“没有记录”和“一直没在看那个位置”。这两者会导向完全不同的处方。
步骤
- 把
auditctl -s和服务状态保存到/root/det/01-status.txt。 - 在
/etc/audit/rules.d/labhub.rules中写入以键cron_change监视/etc/cron.d的写入和属性变更的规则,并加载到内核。 - 用键
outbound_exec把只捕获 64 位execve中可执行文件为/usr/bin/curl的规则加到同一个文件中,并加载。 - 创建
/etc/cron.d/nightly-report并让它调用curl,手动执行一次curl之后,把做了什么写到/root/det/04-trigger.txt。 - 把
ausearch -k outbound_exec -i的最后一个事件保存到/root/det/05-evidence.txt,并在其下写出pid=、exe=、key=三个值。 - 从 journal 中以 JSON 导出 cron 的执行记录,保存到
/root/det/06-cron.json。其中必须包含这台 VM 上每分钟运行的作业(labhub-metrics)的执行行。 - 创建
/usr/local/bin/labhub-helper.sh并赋予执行位,确认cron_change这个键不会留下它的记录,把命令、结果和原因写到/root/det/07-blindspot.txt。 - 添加并加载以键
persistence监视/usr/local/bin的规则,再修改一次文件,并在/root/det/08-closed.txt中确认记录已经留下。 - 把这台主机的检测范围写到
/root/det/09-report.md,分为## 무엇이 남는가、## 무엇이 남지 않는가、## 규칙 목록、## 다음에 할 일(韩文,依次意为“留下了什么”“没有留下什么”“规则列表”“接下来要做什么”)四节。
参考
- 手动用
auditctl加入的规则会在重启后消失。写到/etc/audit/rules.d/并用augenrules --load加载。已加载的规则用auditctl -l查看。 ausearch不加-i时,uid 和系统调用会以数字显示。阅读时请加上-i。- 要把 journal 导出成机器可读的格式,像
journalctl -t CRON -o json --since "-30 min"这样使用-o json。 - 第 7 步中要把键分开的原因:在第 8 步使用同一个键,第 7 步的观察结果就会被推翻。新的位置用新的键来覆盖。
- 常见错误:在加载规则之前就创建文件。审计只看规则加载之后发生的事。
什么处于开启状态
把 auditctl -s 的输出和 systemctl is-active auditd 的结果保存到 /root/det/01-status.txt。其中必须原样包含 enabled 和 backlog_limit 的值。
auditctl -s 会逐行输出内核审计子系统的当前状态。把两条命令的输出接到同一个文件里即可。
监视计划任务目录
在 /etc/audit/rules.d/labhub.rules 中写入一条规则:监视 /etc/cron.d 的写入(w)和属性变更(a),并附上键 cron_change,然后加载到内核。
文件监视规则的形式是 -w <경로> -p <권한> -k <키>(占位符依次为路径、权限、键)。把写在 rules.d 中的内容加载到内核的命令是 augenrules --load,已加载的规则用 auditctl -l 确认。
什么被执行了
用键 outbound_exec 把只捕获 64 位 execve 中可执行文件为 /usr/bin/curl 的规则加到 /etc/audit/rules.d/labhub.rules 中,并加载到内核。
系统调用规则的形式是 -a always,exit -F arch=b64 -S <시스콜> -F <필터> -k <키>(占位符依次为系统调用、过滤条件、键)。按可执行文件路径收窄的过滤字段名是 exe。仅靠文件监视,看不到“什么被执行了”。
制造事件
创建 /etc/cron.d/nightly-report,让它在凌晨三点调用 curl,然后再手动执行一次 curl。并把做了什么用两行以上写到 /root/det/04-trigger.txt。
必须在加载规则之后创建文件,才会留下记录。curl 不需要真的连到任何地方——它被执行过这件事会以 execve 的形式留下来。
取出记录来阅读
把 ausearch -k outbound_exec -i 的最后一个事件保存到 /root/det/05-evidence.txt,并在其下把 pid=、exe=、key= 三个值各写一行。
不加 -i,uid 和系统调用号会以数字显示。只看最后一个事件的话,可以用 awk/sed 只保留 ausearch 结果中最后一个 ---- 分隔符之后的内容,或者用 tail 截取。
在 journal 中找同一个事件
从 journal 中以 JSON 导出 cron 留下的执行记录,保存到 /root/det/06-cron.json。其中必须包含这台 VM 上每分钟运行的作业(labhub-metrics)的 CMD 行。
用 journalctl -t CRON -o json --since "-30 min",每行会输出一个 JSON。如果还没运行,请等 1 分钟后重新导出。
没有监视的位置
创建 /usr/local/bin/labhub-helper.sh 并赋予执行位,确认 ausearch -k cron_change 中不会出现该路径,并把命令、结果和为什么不留记录,用 120 个字符以上写到 /root/det/07-blindspot.txt。
审计规则只看写下的路径。攻击者不需要新建计划任务,只要修改已预约脚本的内容即可。这一步是要亲自确认,那个位置现在处于监视范围之外。
把空缺的位置覆盖起来
把监视 /usr/local/bin 的写入和属性变更、并附上键 persistence 的规则加到 /etc/audit/rules.d/labhub.rules 并加载,再修改一次 labhub-helper.sh,并在 /root/det/08-closed.txt 中确认记录已经留下。
如果把键设为 cron_change,第 7 步中确认的“不会留下”就会被推翻,前面的步骤也会被破坏。新的位置用新的键来覆盖。必须在规则加载之后修改文件,才会留下记录。
把检测范围写成文档
把这台主机现在留下什么、没有留下什么,写到 /root/det/09-report.md,分为 ## 무엇이 남는가、## 무엇이 남지 않는가、## 규칙 목록、## 다음에 할 일(韩文,依次意为“留下了什么”“没有留下什么”“规则列表”“接下来要做什么”)四节。正文中必须出现三个键名和规则文件路径。
在规则列表一节中贴上 auditctl -l 的结果即可。“没有留下什么”是这份文档中最有价值的一节——它能让下一个人不会相信“什么都会留下”。