TT Lab
开始
学习 学习路径 课程

cron 在凌晨三点执行了 curl

一条规则改写六次

在 TT Lab 中继续学习

目标

针对 24 条合成的进程执行记录编写六条 Sigma 规则。每次都实际运行,用数字确认命中了几条、漏掉了几条,据此逐步收窄规则。

为什么重要

检测规则在现场死掉,原因通常不是语法。规则太宽,误报堆积,人们就不再看告警;规则太窄,只要一个地址变了就什么也抓不到。找到二者之间位置的唯一办法是拿数据去跑。写完规则,用眼睛读一遍觉得“应该能命中”就部署的习惯,是检测缺口最大的成因。

所以本实验每写一条规则,就把它应用到事件记录上。命中的条数和误抓的条数以数字给出后,“加上这个条件会把什么一起带进来”,就不是凭感觉,而是通过观察得知的。这就是检测工程在安全工作中格外像软件工程的原因——规则是代码,事件记录是测试数据。

步骤

  1. 按父进程统计事件记录的条数,保存到 /root/sigma/01-parents.txt。
  2. 把以 cron 为父进程的执行全部抓住的最小规则写到 /root/sigma/02-cron-any.yml。
  3. 收窄为只抓命令行中含有 curl 或 wget 的,写到 /root/sigma/03-outbound.yml。selection 只写一个。
  4. 用过滤器排除发往内部仓库(repo.corp.internal)的正常备份,写到 /root/sigma/04-filtered.yml。在 condition 中使用 not。
  5. 不要写地址,而是用行为来抓的规则,写到 /root/sigma/05-behaviour.yml。有两种:把拉取到的内容通过管道交给 shell,以及挂上 shell 向外连接。必须使用 |re 修饰符。
  6. 把计划任务的外部请求和反弹 shell 拆成以 selection_ 开头的两个选择,用 1 of selection_* 合并,写到 /root/sigma/06-combined.yml。内部仓库过滤器作为公共条件。
  7. 给第 6 步的规则补全发布用的元数据,写到 /root/sigma/07-release.yml。
  8. 把第 3 步和第 7 步的规则的判定结果,用数字和判断写到 /root/sigma/08-review.md。

参考

先浏览数据

按父进程(ParentImage)统计 /opt/lab/fixtures/detection/proc_events.jsonl,保存到 /root/sigma/01-parents.txt。每行有一个路径和它的条数即可。

用 jq -r '.ParentImage' 只取出值,再用 sort | uniq -c 统计。这一步是要养成习惯:写规则之前先看看有什么、有多少。

最小的规则

把以 cron 为父进程的执行全部抓住的最小 Sigma 规则写到 /root/sigma/02-cron-any.yml。只要有必填项(title、logsource、detection)即可。

在 detection 下放一个命名的选择,并把这个名称写到 condition 中。事件的 ParentImage 值是什么,可以在第 1 步的结果中找到。

只要向外的

把第 2 步的规则收窄为只抓命令行中含有 curl 或 wget 的,写到 /root/sigma/03-outbound.yml。detection 中的选择只放一个。

在一个选择中写两个字段是 AND,给一个字段以列表形式提供值是 OR。要查找子串,就在字段名后面加修饰符。

排除一个正常作业

在第 3 步的结果中去掉发往内部仓库(repo.corp.internal)的正常备份,写到 /root/sigma/04-filtered.yml。不要收窄选择,而是另设过滤器,用 not 接到 condition 上。

在 detection 下放两个选择,起不同的名称。condition 的形式是 selection and not <필터이름>(占位符为过滤器名称)。

用行为而不是地址

把抓两种行为的规则写到 /root/sigma/05-behaviour.yml:把拉取到的内容通过管道交给 shell,以及挂上 shell 向外连接。使用 |re 修饰符,并且不要在规则中写目的地址。

正则修饰符的形式是 필드|re: '<정규식>'(占位符依次为字段、正则表达式)。请重新读一下第 1 步中看到的命令行,想想管道字符和 -e /bin/sh 这样的片段意味着什么。两个分支也可以拆成两个选择,再用 1 of 合并。

把两个分支合成一个

把计划任务的外部请求和反弹 shell 拆成以 selection_ 开头的两个选择,用 1 of selection_* 合并,写到 /root/sigma/06-combined.yml。内部仓库过滤器对两个分支都适用。

1 of selection_* 会把名称匹配该模式的选择用 OR 连接起来。过滤器以 and not 接到整个这一组上。目标是实际被入侵的 4 条。

变成可以发布的规则

给第 6 步的规则补全 id、status、description、author、date、references、falsepositives、level、tags,写到 /root/sigma/07-release.yml。抓到的事件必须与第 6 步相同。

id 必须是 UUID 的形式(python3 -c 'import uuid;print(uuid.uuid4())')。status 选用尚未拿生产数据运行过的规则所对应的值,level 则按能抓到反弹 shell 的规则来定。tags 中至少需要一项以 attack. 开头的条目。

用数字留下来

把第 3 步和第 7 步的规则与真值集(实际被入侵的 4 条)对照,写到 /root/sigma/08-review.md。每条规则占一行,写文件名和 matched=、tp=、fp=、fn= 四个值,并在 ## 판단(韩文,意为“判断”)一节中用 120 个字符以上写出要发布什么以及理由。

把 --ids 的结果与真值集比较,亲手数出这些值即可。真值集是第 5 步找到的两条,加上第 3 步找到的条目中不是发往内部仓库的那些。