Sigma Rules

This documentation page describes the parsing of Sigma rules and working with Sigma objects resulting from parsed rules.

Parsing

Programatic Construction

Rule Collections

class sigma.collection.SigmaCollection(rules: ~typing.List[~sigma.rule.SigmaRuleBase], errors: ~typing.List[~sigma.exceptions.SigmaError] = <factory>)

Collection of Sigma rules

classmethod from_dicts(rules: List[dict], collect_errors: bool = False, source: SigmaRuleLocation | None = None) SigmaCollection

Generate a rule collection from list of dicts containing parsed YAML content.

If the collect_errors parameters is set, exceptions are not raised while parsing but collected in the errors property individually for each Sigma rule and the whole SigmaCollection.

classmethod from_yaml(yaml_str: bytes | str | IO, collect_errors: bool = False, source: SigmaRuleLocation | None = None) SigmaCollection

Generate a rule collection from a string containing one or multiple YAML documents.

If the collect_errors parameters is set, exceptions are not raised while parsing but collected in the errors property individually for each Sigma rule and the whole SigmaCollection.

get_output_rules() Iterable[SigmaRuleBase]

Returns an iterator across all rules where the output property is set to true

get_unreferenced_rules() Iterable[SigmaRuleBase]

Returns an iterator across all rules that are not referenced by any other rule

classmethod load_ruleset(inputs: List[str | Path], collect_errors: bool = False, on_beforeload: Callable[[Path], Path | None] | None = None, on_load: Callable[[Path, SigmaCollection], SigmaCollection | None] | None = None, recursion_pattern: str = '**/*.yml') SigmaCollection

Load a ruleset from a list of files or directories and construct a SigmaCollection object.

Parameters:

inputs – List of strings and pathlib.Path objects that reference files or

directories that should be loaded. :param collect_errors: parse or verification errors are collected in SigmaRuleBase objects instead of raising them immediately. Defaults to False. :param on_beforeload: Optional function that is called for each path to a Sigma rule before the parsing and construction of the SigmaCollection object is done. The path returned by this function is used as input. A rule path is skipped if None is returned. :param on_load: Optional function that is called after the SigmaCollection was constructed from the path. The path and the SigmaCollection object are passed to this function and it is expected to return a SigmaCollection object that is merged in the collection of the ruleset or None if the generated collection should be skipped. :param recursion_pattern: Pattern used to recurse into directories, defaults to **/*.yml.

Returns:

SigmaCollection of all sigma rules contained in given paths.

classmethod merge(collections: Iterable[SigmaCollection]) SigmaCollection

Merge multiple SigmaCollection objects into one and return it.

classmethod resolve_paths(inputs: List[str | Path], recursion_pattern: str = '**/*.yml') Iterable[Path]

Resolve list of paths inputs that can contain files as well as directories into a flat list of files matching resursion_pattern.

resolve_rule_references()

Resolve rule references in correlation rules to the actual rule objects and sort the rules by reference order (rules that are referenced by other rules come first).

This must be called before referencing rules are converted into queries to make references available.

Rule Object Model

SigmaRule

class sigma.rule.SigmaRule(title: str = '', id: ~uuid.UUID | None = None, name: str | None = None, taxonomy: str = 'sigma', related: ~sigma.rule.SigmaRelated | None = None, status: ~sigma.rule.SigmaStatus | None = None, description: str | None = None, references: ~typing.List[str] = <factory>, tags: ~typing.List[~sigma.rule.SigmaRuleTag] = <factory>, author: str | None = None, date: ~.datetime.date | None = None, modified: ~.datetime.date | None = None, fields: ~typing.List[str] = <factory>, falsepositives: ~typing.List[str] = <factory>, level: ~sigma.rule.SigmaLevel | None = None, errors: ~typing.List[~sigma.exceptions.SigmaError] = <factory>, source: ~sigma.exceptions.SigmaRuleLocation | None = None, custom_attributes: ~typing.Dict[str, ~typing.Any] = <factory>, logsource: ~sigma.rule.SigmaLogSource = <factory>, detection: ~sigma.rule.SigmaDetections = <factory>)

A single Sigma rule.

classmethod from_dict(rule: dict, collect_errors: bool = False, source: SigmaRuleLocation | None = None) SigmaRule

Convert Sigma rule parsed in dict structure into SigmaRule object.

if collect_errors is set to False exceptions are collected in the errors property of the resulting SigmaRule object. Else the first recognized error is raised as exception.

to_dict() dict

Convert rule object into dict.

SigmaLogSource

class sigma.rule.SigmaLogSource(category: str | None = None, product: str | None = None, service: str | None = None, source: sigma.exceptions.SigmaRuleLocation | None = None)
classmethod from_dict(logsource: dict, source: SigmaRuleLocation | None = None) SigmaLogSource

Returns SigmaLogSource object from dict with fields.

SigmaDetections

class sigma.rule.SigmaDetections(detections: Dict[str, SigmaDetection], condition: List[str], source: SigmaRuleLocation | None = None)

Sigma detection section including named detections and condition.

SigmaDetection

class sigma.rule.SigmaDetection(detection_items: List[SigmaDetectionItem | SigmaDetection], source: SigmaRuleLocation | None = None, item_linking: Type[ConditionAND] | Type[ConditionOR] | None = None)

A detection is a set of atomic event defitionions represented by SigmaDetectionItem instances. SigmaDetectionItems of a SigmaDetection are OR-linked.

A detection can be defined by:

  1. a mapping between field/value pairs that all should appear in matched events.

  2. a plain value

  3. a list of plain values or mappings defined and matched as in 1 where at least one of the items should appear in matched events.

add_applied_processing_item(processing_item: ProcessingItem | None)

Propagate processing item to all contained detection items.

classmethod from_definition(definition: Mapping | Sequence | str | int, source: SigmaRuleLocation | None = None) SigmaDetection

Instantiate an appropriate SigmaDetection object from a parsed Sigma detection definition.

postprocess(detections: SigmaDetections, parent: sigma.condition.ConditionItem | None = None) ConditionAND | ConditionOR

Convert detection item into condition tree element

to_plain() Dict[str, str | int | None] | List[str]

Returns a dictionary or list representation of the detection.

SigmaDetectionItem

class sigma.rule.SigmaDetectionItem(field: str | None, modifiers: ~typing.List[~typing.Type[~sigma.modifiers.SigmaModifier]], value: ~typing.List[~sigma.types.SigmaType], value_linking: ~typing.Type[~sigma.conditions.ConditionAND] | ~typing.Type[~sigma.conditions.ConditionOR] = <class 'sigma.conditions.ConditionOR'>, source: ~sigma.exceptions.SigmaRuleLocation | None = None, auto_modifiers: dataclasses.InitVar[bool] = True)

Single Sigma detection definition

A detection consists of: * an optional field name * a list of value modifiers that can also be empty * the mandatory value or a list of values (internally it’s always a list of values)

By default all values are OR-linked but the ‘all’ modifier can be used to override this behavior.

If the auto_modifiers parameter is set to False, modifiers are not automatically applied to the values. This shouldn’t normally be used, but only in test scenarios.

apply_modifiers()

Applies modifiers to detection and values

disable_conversion_to_plain()

Mark detection item as not convertible to plain data type. This is required in cases where the value and original value get out of sync, e.g. because transformation are applied and conversion with to_plain() would yield an outdated state.

classmethod from_mapping(key: str | None, val: List[int | float | str] | int | float | str | None, source: SigmaRuleLocation | None = None) SigmaDetectionItem

Constructs SigmaDetectionItem object from a mapping between field name containing modifiers and a value. This also supports keys containing only value modifiers which results in a keyword detection.

The value accepts plain values as well as lists of values and resolves them into the value list always contained in a SigmaDetectionItem instance.

classmethod from_value(val: List[str | int] | int | str, source: SigmaRuleLocation | None = None) SigmaDetectionItem

Convenience method for from_mapping(None, value).

is_keyword() bool

Returns True if detection item is a keyword detection without field reference.

postprocess(detections: SigmaDetections, parent: sigma.condition.ConditionItem | None = None) ConditionAND | ConditionOR | ConditionFieldEqualsValueExpression | ConditionValueExpression

Minimal default postprocessing implementation for classes which don’t bring their own postprocess method. Just sets the parent and source property.

to_plain() Dict[str, str | int | None] | List[str]

Convert detection item into plain Python type, that can be:

  • a plain value if it is a single plain keyword value.

  • a list of values if it is a list of keyword values

  • a dict in all other cases (detection item bound to field or keyword with modifiers)

value_linking

alias of ConditionOR

SigmaRuleTag

class sigma.rule.SigmaRuleTag(namespace: str, name: str, source: sigma.exceptions.SigmaRuleLocation | None = None)
classmethod from_str(tag: str, source: SigmaRuleLocation | None = None) SigmaRuleTag

Build SigmaRuleTag class from plain text tag string.

SigmaLevel

class sigma.rule.SigmaLevel(value)

An enumeration.

SigmaStatus

class sigma.rule.SigmaStatus(value)

An enumeration.

Sigma Data Types

SigmaString

class sigma.types.SigmaString(s: str | None = None)

Strings in Sigma detection values containing wildcards.

contains_placeholder(include: List[str] | None = None, exclude: List[str] | None = None) bool

Check if string contains placeholders and if any placeholder name is

  • contained on the include list (if there is one)

  • not contained on the include list (if there is one)

It is sufficient that one placeholder matches these conditions. The purpose of this method is to determine if there are placeholders for further processing.

contains_special() bool

Check if string contains special characters.

convert(escape_char: str | None = '\\', wildcard_multi: str | None = '*', wildcard_single: str | None = '?', add_escaped: str = '', filter_chars: str = '') str

Convert SigmaString into a query string or pattern. The following parameters allow to change the behavior:

  • escape_char: the character used to escape special characters. By default these are only the wildcard characters.

  • wildcard_multi and wildcard_single: strings that should be output as wildcards for multiple and single characters.

  • add_escaped: characters which are escaped in addition to the wildcards

  • filter_chars: characters that are filtered out.

Setting one of the wildcard or multiple parameters to None indicates that this feature is not supported. Appearance of these characters in a string will raise a SigmaValueError.

endswith(val: str | SpecialChars) bool

Check if string ends with a given string or special character.

insert_placeholders() SigmaString

Replace %something% placeholders with Placeholder stub objects that can be later handled by the processing pipeline. This implements the expand modifier.

replace_placeholders(callback: Callable[[Placeholder], Iterator[str | SpecialChars | Placeholder]]) List[SigmaString]

Iterate over all placeholders and call the callback for each one. The callback is called with the placeholder instance as argument and yields replacement values (plain strings or SpecialChars instances). Each yielded replacement value is concatenated to the SigmaString prefix before the placeholder and the method is called recursively with the suffix after the placeholder. All placeholder replacements are combined with all returned SigmaString suffixes. Therefore, the callback could be called multiple times with the same placeholder instance and should return the same results to ensure a consistent result.

The callback can return a plain string, a SpecialChars instance (for insertion of wildcards) or a Placeholder (e.g. to keep the placeholder for later processing pipeline items).

replace_with_placeholder(regex: Pattern, placeholder_name: str) SigmaString

Replace all occurrences of string part matching regular expression with placeholder.

Parameters:
  • regex (Pattern) – regular expression that should be matched.

  • placeholder_name (str) – name of placeholder that should be inserted.

Returns:

Returns a string with the replacement placeholders.

Return type:

SigmaString

startswith(val: str | SpecialChars) bool

Check if string starts with a given string or special character.

to_plain()

Return plain string representation of SigmaString, equivalent to converting it with str().

SigmaNumber

class sigma.types.SigmaNumber(number: int | float)

Numeric value type

SigmaBool

class sigma.types.SigmaBool(boolean: bool)

Boolean value type

SigmaNull

class sigma.types.SigmaNull(dummy: Any | None = None)

Empty/none/null value

SigmaRegularExpression

class sigma.types.SigmaRegularExpression(regexp: str, flags: ~typing.Set[~sigma.types.SigmaRegularExpressionFlag] = <factory>)

Regular expression type

compile()

Verify if regular expression is valid by compiling it

escape(escaped: Tuple[str] = (), escape_char: str = '\\', escape_escape_char: bool = True, flag_prefix: bool = True) str

Escape strings from escaped tuple as well as escape_char itself (can be disabled with escape_escape_char) with escape_char. Prepends a (?…) expression with set flags (i, m and s) if flag_prefix is set.

SigmaCIDRExpression

class sigma.types.SigmaCIDRExpression(cidr: str, source: SigmaRuleLocation | None = None)

CIDR IP address range expression type

expand(wildcard: str = '*') List[str]

Convert CIDR range into a list of wildcard patterns or plain CIDR notation. The following parameters allow to change the behavior:

  • wildcard: string that should be output as wildcard. Usually not required because this is passed to SigmaString that generates a wildcard pecial character from ‘*’ that is converted into possible individual wildcard characters.

Setting wildcard to None indicates that this feature is not need and the query language handles CIDR notation properly.

SigmaCompareExpression

class sigma.types.SigmaCompareExpression(number: SigmaNumber, op: CompareOperators, source: SigmaRuleLocation | None = None)

Type for numeric comparison.

class CompareOperators(value)

An enumeration.

SigmaQueryExpression

class sigma.types.SigmaQueryExpression(expr: str, id: str)

Special purpose type for passing a query part (e.g. list lookups in placeholders) directly into the generated query. The query string may contain a {field} placeholder, which is replaced with the field name contained in the detection item containing the query expression. This is done by the finalize method.

Because this is very specific to the target language, it has to be used in late stages of the conversion process by backend-specific processing pipelines or the backend itself.