Write a Sigma rule and run it

Sigma is the shared YAML format detection engineers use to describe an attack once and run it on any SIEM. TB's detect library reads a practical subset of it. You'll load a rule, write your own, and run a whole folder of rules over Linux, web and Windows logs, all in your browser.

1.Read a Sigma rule

TB comes with a few sample rules in apps/data/sigma. Here is the SSH brute-force one.

import fs
say(fs.read("apps/data/sigma/ssh_brute_force.yml"))

The detection part says what to match (selection) and when to fire (condition): more than ten matches from one IP within five minutes.

2.Run it over a log

detect.sigma loads a rule from a file (or from text). detect.run runs a list of rules over records.

import logs
import detect

let rule = detect.sigma("apps/data/sigma/ssh_brute_force.yml")
say(rule.name, "/", rule.level)

let records = logs.read("apps/data/auth.log", "auth")
for alert in detect.run([rule], records) {
  say(f"{alert.level}: {alert.rule} from {alert.by}, {alert.count} times")
}

3.Write your own rule

Field modifiers like |contains, |startswith and |endswith match part of a value. This rule catches path traversal in web requests.

import logs
import detect

let yaml = [
  "title: Path traversal in a web request",
  "level: high",
  "detection:",
  "  selection:",
  "    path|contains: '../'",
  "  condition: selection",
].join("\n")

let records = logs.read("apps/data/access.log", "apache")
for alert in detect.run([detect.sigma(yaml)], records) {
  for r in alert.records {
    say(r.when, r.ip, r.status, r.path)
  }
}

4.Windows events

The same rules work on Windows Security events exported as JSON or CSV. This one looks for PowerShell started with a hidden, base64-encoded command, and encode.unbase64 shows what it really said.

import logs
import detect
import encode
import re

let rule = detect.sigma("apps/data/sigma/win_encoded_powershell.yml")
let records = logs.read("apps/data/windows_security.json", "windows")
for alert in detect.run([rule], records) {
  let cmd = alert.records[0].command_line
  say(alert.level, alert.rule)
  let blob = re.match("-[eE]nc\\w* (?P<b64>\\S+)", cmd)
  if blob != nil {
    say("Decoded:", encode.unbase64(blob.b64, "utf-16le"))
  }
}

5.Run a whole folder

Real detection is many rules at once. detect.sigma_folder loads every .yml in a folder.

import logs
import detect
import report

let rules = detect.sigma_folder("apps/data/sigma")
let records = logs.read("apps/data/windows_security.json", "windows")
let alerts = detect.run(rules, records)
say(report.table(alerts, ["level", "rule", "count", "first_when"]))

Where next

The Sigma runner app runs a folder of rules over any log files from the command line. The detect reference lists the supported Sigma features and TB's own rule maps, which can do everything shown here without YAML.