Skip to main content

Sigma

The Sigma query frontend makes it possible to execute Sigma rules in VAST. This means you can provide a Sigma rule instead of a VASTQL expression when querying data. For example:

vast export json < sigma-rule.yaml

Sigma defines a YAML-based rule language along with a compiler that transforms rules into the native query languages of SIEM systems. VAST takes a different approach and compiles the Sigma query directly into a native query expression, without going through the Python tooling provided by the SigmaHQ project. This has numerous advantages in exploiting the richer type system of VAST. The translation process looks as follows:

Sigma Query Frontend Sigma Query Frontend

Usage

To use the Sigma frontend, install the sigma plugin. Then use the vast export command to provide a Sigma rule on standard input:

vast export <format> < sigma-rule.yaml

The <format> placeholder represents an output format, such as json or csv, and sigma-rule.yaml a file containing a Sigma rule.

Search Identifiers

The Sigma rule YAML format requires a detection attribute that includes a map of named sub-expression called search identifiers. In addition, detection must include a final condition that combines search identifiers using boolean algebra (AND, OR, and NOT) or syntactic sugar to reference groups of search expressions, e.g., using the 1/all of * or plain wildcard syntax.

Consider the following Sigma detection embedded in a rule:

detection:
foo:
a: 42
b: "evil"
bar:
c: 1.2.3.4
condition: foo or not bar

VAST translates this rule piece by building a symbol table of all keys (foo and bar). Each sub-expression is a valid VAST expression itself:

  1. foo: a == 42 && b == "evil"
  2. bar: c == 1.2.3.4

Finally, VAST combines the expression according to the condition:

(a == 42 && b == "evil") || ! (c == 1.2.3.4)
Rich YAML Typing

Because VAST has a beefed up YAML parser that performs type inference, the YAML snippet c: 1.2.3.4 is parsed as a key-value pair with types string and address. This means that we get the rich type system of VAST for free.

Taxonomy

Sigma comes with a taxonomy to facilitate rule sharing by standardizing field names of the supported data sources.

Missing Definitions

VAST currently does not ship with a taxonomy to transparently map the canonical Sigma fields to an equivalent in VAST. We will ship the missing mappings in the future. To date, you must either use VAST concepts to re-implement the mappings or wait until we have provided them.

Comparison

VAST and Sigma have many commonalities. They both support flexible construction of search expressions using boolean algebra (AND, OR, NOT) and offer multiple ways to define predicates and sub-expression. But there also exist differences in expressiveness and intent. This section compares the two systems.

Expressiveness

The majority of rule definitions include combinations of exact string lookups, substring searches, or pattern matches. Sigma uses modifiers to select a concrete operator for given search predicate. Without a modifier specification, Sigma uses equality comparison (==) of field and value. For example, the contains modifier changes the operator to substring search, and the re modifier switches to a regular expression match. The now "legacy" sigma compiler lacks support for ordering relationships, such as less-than comparison of numerical values, e.g., x < 42 or timestamp >= 2021-02. The pySigma project addresses this with the additional modifiers lt, lte, gt, gte.

Compatibility

VAST's support for Sigma is still in the early stages and does not support the full language specification. Most notable, the concept of a "value" is different:

  • VAST does not yet offer case-insensitive string search
  • VAST does not yet treat * and ? wildcards in strings as wildcards

The table below shows the current implementation status of modifiers, where ✅ means implemented, 🚧 not yet implemented but possible, and ❌ not yet supported by VAST's query engine:

ModifierUsesigmacVAST
containsperform a substring search with the value
startswithmatch the value as a prefix
endswithmatch the value as a suffix
base64encode the value with Base64
base64offsetencode value as all three possible Base64 variants
utf16le/widetransform the value to UTF16 little endian🚧
utf16betransform the value to UTF16 big endian🚧
utf16transform the value to UTF16🚧
reinterpret the value as regular expression🚧
cidrinterpret the value as a IP CIDR
allchanges the expression logic from OR to AND
ltcompare less than (<) the value
ltecompare less than or equal to (<=) the value
gtcompare greater than (>) the value
gtecompare greater than or equal to (>=) the value
expandexpand value to placeholder strings, e.g., %something%