kotoba-lang/sigma

GitHub: kotoba-lang/sigma

该库以零依赖的可移植 Clojure 将 Sigma 检测规则建模为纯 EDN 数据,并提供校验、YAML 转换与纯事件匹配能力。

Stars: 0 | Forks: 0

# sigma-clj (检测规则) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/kotoba-lang/sigma/actions/workflows/ci.yml) 在可移植的 Clojure 中 **将 Sigma 检测规则作为 EDN/Clojure 数据处理** —— 每个 命名空间都是 `.cljc`,且 **运行时零第三方依赖**,因此它可以在 JVM、 ClojureScript 和 Clojure-on-WASM 主机 (SCI) 上运行。Sigma 规则是纯数据,你可以 对其进行 `assoc`、`diff`、存储在 Datomic 中,或动态生成;该库在此基础上添加了结构性 校验、YAML 结构 ↔ EDN 转换器,以及一个纯事件匹配器。 它是 [ghosthacker](https://github.com/com-junkawasaki/ghosthacker)(安全工具套件) 的天然搭档,也是本组织中其他可复用 `*-clj` 核心 ([bpmn-clj](https://github.com/com-junkawasaki/bpmn-clj)、 [dmn-clj](https://github.com/com-junkawasaki/dmn-clj))的兄弟项目。 ## 为什么需要共享库 (组织归属) 根据三组织规则,**可复用的**检测模型位于 **com-junkawasaki** 中; 驱动具体检测流水线的 **公益行为者实例** 位于 **etzhayyim** 中;任何 **商业/私有部署** 则位于 **gftdcojp** 中。sigma-clj 就是那个依赖项 —— 它不包含任何领域规则,也没有引擎绑定(那些都是 由宿主注入的端口)。Sigma 规则本身属于使用该规则的组织。 ## 模型:作为 EDN 的 Sigma 规则 (`sigma.model`) 规则是带有命名空间 `:sigma/*` 的 map;selection 使用字符串作为键(保留 包括 `|modifier` 后缀在内的 YAML 字段键格式): ``` {:sigma/id "bf-01" :sigma/title "Brute Force Login Attempt" :sigma/level :high :sigma/logsource {:sigma/product "windows" :sigma/service "security"} :sigma/detection {:sigma/selections {"sel" {"EventID" [4625] "TargetUserName|contains" ["adm"]} "filt" {"IpAddress" ["127.0.0.1"]}} :sigma/condition "sel and not filt"}} ``` 一个对线程友好的构建器: ``` (require '[sigma.model :as m]) (def rule (-> (m/rule "bf-01" "Brute Force Login" {:level :high :logsource {:sigma/product "windows" :sigma/service "security"}}) (m/add-selection "sel" {"EventID" [4625] "TargetUserName|contains" ["adm"]}) (m/add-selection "filt" {"IpAddress" ["127.0.0.1"]}) (m/set-condition "sel and not filt"))) (m/selection-names rule) ;=> #{"sel" "filt"} (m/condition rule) ;=> "sel and not filt" ``` ## 校验 (`sigma.validate`) `problems` 返回一个包含 `{:sigma/severity :error|:warn :sigma/code :sigma/id :sigma/msg}` 的 vector; 当且仅当不存在 `:error` 时 `valid?` 为真(警告仅作参考): ``` (require '[sigma.validate :as v]) (v/valid? rule) ;=> true (v/problems broken) ;=> [{:sigma/severity :error :sigma/code :condition/unknown-selection …}] ``` 错误:条件引用了未定义的 selection、未知的字段修饰符。 警告:未知的 `:sigma/level`(参考性建议 —— Sigma 规范会不断演进;当前已知的级别有 `:informational` `:low` `:medium` `:high` `:critical`)、条件中的 glob 没有匹配到任何 已定义的 selection。 ## YAML 结构 ↔ EDN (`sigma.yaml`) `from-data` 将一个 **已解析的** Sigma YAML map(字符串键,类似于 `clj-yaml` 等 YAML 库生成的格式)转换为 `:sigma/*` 模型。`to-data` 执行 反向操作。**这里绝不解析原始 YAML 文本** —— 请注入你所用平台的 YAML 解析器: ``` (require '[sigma.yaml :as y]) ;; Host already parsed YAML to a Clojure map with string keys: (def data {"title" "Brute Force Login" "id" "bf-01" "level" "high" "logsource" {"product" "windows" "service" "security"} "detection" {"sel" {"EventID" [4625] "TargetUserName|contains" ["adm"]} "filt" {"IpAddress" ["127.0.0.1"]} "condition" "sel and not filt"}}) (def rule (y/from-data data)) (:sigma/level rule) ;=> :high (= data (y/to-data rule)) ;=> true (round-trip lossless) ``` ## 端口 (`sigma.ports`) 宿主通过注入 `IField`,使得 sigma-clj 绝不预设事件 schema: ``` IField extract [field-name event] — String field name + event map → value ``` `default-ports` 会优先尝试字符串键,然后再尝试关键字键 —— 这对于普通 map 来说已经足够。 对于结构化的日志 schema(嵌套 map、schema registry、带类型的字段),请提供 自定义的 `IField` 实现。 ## 执行 (`sigma.execute` + `sigma.ports`) 一个 **纯粹的事件匹配器** —— 没有 I/O 操作,也没有副作用。将每个具名 selection 编译 为谓词,然后对条件表达式进行求值: ``` (require '[sigma.execute :as e] '[sigma.ports :as p]) (def pts (p/default-ports)) (e/matches? pts rule {"EventID" 4625 "TargetUserName" "administrator" "IpAddress" "10.0.0.1"}) ;=> true (sel=true, filt=false) (e/matches? pts rule {"EventID" 4625 "TargetUserName" "administrator" "IpAddress" "127.0.0.1"}) ;=> false (filtered: filt=true) ``` **条件表达式** 支持标识符、`and` / `or` / `not`、括号、 `1 of `(任何名称匹配该 glob 的 selection,例如 `sel*`),以及 `all of them`。 **字段修饰符**(字段键上的管道符后缀): | 修饰符 | 语义 | |--------------|----------------------------------------------------| | `contains` | 字段值(作为字符串)包含判定条件 | | `startswith` | 字段值以判定条件开头 | | `endswith` | 字段值以判定条件结尾 | | `re` | 字段值中能 `re-find` 匹配到作为判定条件的正则表达式 | | `gt` | 字段值(数字)> 判定条件(数字) | | `lt` | 字段值(数字)< 判定条件(数字) | | `all` | 对值列表进行 AND 操作,而不是 OR | 修饰符可以组合使用:`"Cmd|contains|all"` 表示该字段必须包含列出的 **所有** 值。`default-ports` 处理普通的以字符串/关键字为键的事件 map;对于结构化 schema,请替换为自定义的 `IField`。 **安全协同**:sigma-clj 可以与 [ghosthacker](https://github.com/com-junkawasaki/ghosthacker) 天然配合 —— ghosthacker 可以 根据其安全工具的输出生成结构化的事件 map,而 sigma-clj 无需任何额外的依赖即可针对这些 map 评估 Sigma 检测规则。 ## 测试 ``` clojure -X:test ```
标签:Clojure, EDN, Sigma规则, 云计算, 安全工程, 日志检测, 目标导入, 规则引擎, 零依赖