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

cron 在凌晨三点执行了 curl

规则是数据结构,不是句子

在 TT Lab 中继续学习

一句话总结

Sigma 是用与工具无关的 YAML 来写“在这份日志中找这样的东西”的格式。必填项只有 title、logsource、detection 三个,检测的主体是 detection 中命名的若干选择(selection),以及把它们组装起来的一行 condition。

为什么需要它

检测规则的语法因工具而异。同样是“计划任务向外发出了请求”,在搜索引擎中写成查询语句,在日志管道中写成过滤器,在 EDR 中写成它自己界面里的表单。换一家公司,规则就要从头重写。更糟的是规则无法共享。某个团队做出了能抓住新手法的规则,其他团队也得翻译成自己工具的语言,而翻译时会悄悄漏掉一个条件。

Sigma 在它们中间放了一种格式。规则用 YAML 书写,由后端把它翻译成各工具的查询语句。这样,规则就成了人可以阅读、评审并提交到 git 的代码,工具则成了可以更换的后端。

工作原理

一条规则的骨架如下。

title: 예약 작업이 사외로 요청했다
id: 8b2f5f4a-1d3c-4c22-9f0e-6a7b1c2d3e4f
status: test
description: cron 밑에서 curl·wget 이 실행되고 목적지가 사내가 아닌 경우
logsource:
  product: linux
  category: process_creation
detection:
  selection:
    ParentImage|endswith: '/cron'
    CommandLine|contains:
      - 'curl'
      - 'wget'
  filter_internal:
    CommandLine|contains: 'repo.corp.internal'
  condition: selection and not filter_internal
level: high

规则文档明确规定的规则有三条。title、logsource、detection 是必填的,status 是 stable、test、experimental、deprecated、unsupported 之一,level 是 critical、high、medium、low、informational 之一。logsource 用 category(Web 服务器、防火墙这样的类别)、product(windows、linux 这样的产品)、service(该产品中的服务)来限定针对哪种日志(日志源文档)。

最容易混淆的地方是映射和列表的含义不同。在一个选择中并列多个字段是 AND,给一个字段多个值则是 OR。上面的例子中,ParentImage 和 CommandLine 必须同时满足,而 curl 和 wget 只要满足其中一个即可。

condition 是把这些选择组装起来的一门小语言(条件文档)。使用 and、or、not 和括号,名称有多个时用 1 of selection_*(任意一个)和 all of selection_*(全部)来归拢。也有 1 of them、all of them,但文档不建议在共享规则中使用这两者——因为之后再加一个选择时,规则的含义会悄无声息地改变。

值的比较方式由字段名后面的修饰符决定(修饰符文档)。|contains、|startswith、|endswith、|re 常用,像 |contains|all 这样连起来,就表示“列出的值必须全部包含”。初学者一定会栽一次的地方是 |contains 的词边界。为了找 nc 而写 CommandLine|contains: 'nc',rsync 也会被命中。因为字符串里 n 后面跟着 c。

在现场相遇的样子

现场中规则死掉的原因,大多是这两个之一。一个是误报太多,没人看了。起初告警一响人们会去确认,但如果十次里有九次是正常的备份作业,从第十一次开始就没人再点开了。所以把规则写得很宽、“先全抓,以后再收窄”的计划,几乎总是失败。

另一个是把地址写死在规则里。这次事件的目的地是 cdn.updates-cache.net,就把这个字符串放进规则,下周域名一换,规则就什么也抓不到了。长寿的规则写的不是地址,而是行为——比如把拉取到的内容直接通过管道交给 shell,或者挂上 shell 向外连接。

此外,重要的是不要把元数据当成装饰。如果 falsepositives 里写了一行“正常备份作业”,凌晨三点被呼叫的人三分钟就能判断;没有这一行,就要花三十分钟。references 和 tags 也有同样的价值。

下一项实验要做什么

实验中会拿到 24 条合成的进程执行记录,编写六条规则。从最小的规则开始逐步收窄,用过滤器排除正常的备份作业,编写用行为而非地址来抓取的规则,再用 1 of 把两个分支合并。每写一条规则都要在事件记录上实际运行,用数字确认命中了几条、漏掉了几条。本实验只处理文件,所以在实验 Pod 中运行。