sigma.schema module

Sigma rule schema is the core functionality of this package. The rule schema allows you to generically read and write Sigma rules in Python. Rules can be loaded from a dictionary or directly from a YAML file. You can also reproduce compliant Sigma rules from in-memory representations with the Rule.to_sigma() method. This can be used to load, modify and save sigma rules without conversion if needed.

Sigma rule detection conditions can also be parsed using the pyparsing package into a python-native format, which is normally used in conjunction with a serializer.

Loading and Inspecting a Rule
from sigma.schema import Rule

rule = Rule.from_yaml("path/to/rule.yml")

# Retrieve common properties
print(rule.title)
print(rule.detection.condition)
print(rule.tags)
print(rule.author)

# Retrieve a parsed expression representing the full detection condition
print(rule.detection.expression)
class sigma.schema.BaseCorrelation(*, action: Literal['correlation'], name: str, rule: Union[str, List[str]], type: sigma.schema.CorrelationType, timespan: sigma.schema.ConstrainedStrValue, level: sigma.schema.RuleLevel, **extra_data: Any)

Bases: pydantic.main.BaseModel

action: Literal['correlation']

A correlation action

group_by: Optional[Union[str, List[str]]]

Optional field to group results by

level: sigma.schema.RuleLevel

A rule level to apply to the correlation of all rules

name: str

Name of this correlation

rule: Union[str, List[str]]

List of rule titles or correlation names also specified in the same file.

timespan: str

A timespan used for correlating events (e.g. 5m, 3d or 30s)

type: sigma.schema.CorrelationType

Type of correlation to be used

class sigma.schema.Correlation(data: Union[sigma.schema.CountCorrelation, sigma.schema.TemporalCorrelation], rules: List[Union[sigma.schema.Rule, sigma.schema.Correlation]])

Bases: object

An object representing a collection of rules bound by a correlation

class sigma.schema.CorrelationGreaterThan(*, gt: int)

Bases: sigma.schema.CorrelationSimpleCondition

gt: int
class sigma.schema.CorrelationGreaterThanEqual(*, gte: int)

Bases: sigma.schema.CorrelationSimpleCondition

gte: int
class sigma.schema.CorrelationLessThan(*, lt: int)

Bases: sigma.schema.CorrelationSimpleCondition

lt: int
class sigma.schema.CorrelationLessThanEqual(*, lte: int)

Bases: sigma.schema.CorrelationSimpleCondition

lte: int
class sigma.schema.CorrelationRange(*, range: sigma.schema.ConstrainedStrValue)

Bases: pydantic.main.BaseModel

property maximum: int
property minimum: int
range: str
class sigma.schema.CorrelationSimpleCondition

Bases: pydantic.main.BaseModel

property value: int
class sigma.schema.CorrelationType(value)

Bases: str, enum.Enum

An enumeration.

EVENT_COUNT = 'event_count'
TEMPORAL = 'temporal'
VALUE_COUNT = 'value_count'
class sigma.schema.CountCorrelation(*, action: typing.Literal['correlation'], name: str, rule: typing.Union[str, typing.List[str]], type: typing.Union[typing.Literal[<CorrelationType.EVENT_COUNT: 'event_count'>], typing.Literal[<CorrelationType.VALUE_COUNT: 'value_count'>]], timespan: sigma.schema.ConstrainedStrValue, level: sigma.schema.RuleLevel, condition: typing.Union[sigma.schema.CorrelationLessThan, sigma.schema.CorrelationLessThanEqual, sigma.schema.CorrelationGreaterThan, sigma.schema.CorrelationGreaterThanEqual, sigma.schema.CorrelationRange], **extra_data: typing.Any)

Bases: sigma.schema.BaseCorrelation

condition: Union[sigma.schema.CorrelationLessThan, sigma.schema.CorrelationLessThanEqual, sigma.schema.CorrelationGreaterThan, sigma.schema.CorrelationGreaterThanEqual, sigma.schema.CorrelationRange]
type: Union[Literal[<CorrelationType.EVENT_COUNT: 'event_count'>], Literal[<CorrelationType.VALUE_COUNT: 'value_count'>]]

Type of correlation to be used

class sigma.schema.IncludeSchema(*, action: Literal['include'], filename: pydantic.types.FilePath)

Bases: pydantic.main.BaseModel

Defines a YAML document which includes an outside rule or correlation

action: Literal['include']
filename: pydantic.types.FilePath
load() sigma.schema.Rule

Load the specified included file

class sigma.schema.LowercaseString

Bases: str

class sigma.schema.Rule(*, title: sigma.schema.ConstrainedStrValue, id: uuid.UUID = None, related: List[sigma.schema.RuleRelation] = None, status: sigma.schema.RuleStatus = None, description: sigma.schema.ConstrainedStrValue = None, author: str = None, license: str = None, references: List[str] = None, logsource: sigma.schema.RuleLogSource, detection: sigma.schema.RuleDetection, fields: List[str] = None, falsepositives: List[Union[None, str]] = None, level: sigma.schema.RuleLevel = None, tags: List[sigma.schema.RuleTag] = None, date: Optional[Union[sigma.schema.SimpleDate, str]] = None, modified: Optional[Union[sigma.schema.SimpleDate, str]] = None, **extra_data: Any)

Bases: pydantic.main.BaseModel

Sigma Rule Specification

class Config

Bases: object

extra = 'allow'
schema_extra = {'examples': [{'title': 'Windows Credential Editor', 'id': '7aa7009a-28b9-4344-8c1f-159489a390df', 'description': 'Detects the use of Windows Credential Editor (WCE)', 'status': 'experimental', 'author': 'Florian Roth', 'references': ['https://www.ampliasecurity.com/research/windows-credentials-editor/'], 'date': '2019/12/31', 'modified': '2021/07/15', 'tags': ['attack.credential_access', 'attack.t1003.001', 'attack.s0005'], 'logsource': {'category': 'process_creation', 'product': 'windows'}, 'detection': {'selection1': {'Imphash': ['a53a02b997935fd8eedcb5f7abab9b9f', 'e96a73c7bf33a464c510ede582318bf2']}, 'selection2': {'CommandLine|endswith': '.exe -S', 'ParentImage|endswith': '\\services.exe'}, 'filter': {'Image|endswith': '\\clussvc.exe'}, 'condition': '( selection1 or selection2 ) and not filter'}, 'falsepositives': ['Another service that uses a single -s command line switch'], 'level': 'critical'}]}
author: Optional[str]

Creator of the rule

date: Optional[Union[sigma.schema.SimpleDate, str]]

The date the rule was created. This should be YYYY-MM-DD or YYYY/MM/DD. If the field is not formatted in this way, it will be saved as a simple string.

description: Optional[str]

A short description of the rule and the malicious activity that can be detected (max. 65,535 characters).

detection: sigma.schema.RuleDetection

A set of search-identifiers that represent searches on log data.

falsepositives: Optional[List[Union[None, str]]]

A list of known false positives that may occur.

fields: Optional[List[str]]

A list of log fields that could be interesting in further analysis of the event and should be displayed to the analyst.

classmethod from_sigma(definition: Dict[str, Any]) sigma.schema.Rule

Alias for parse_obj to be more expressive

classmethod from_yaml(path: Union[str, pathlib.Path]) sigma.schema.Rule

Load a rule from a YAML file

id: Optional[uuid.UUID]

Sigma rules should be identified by a globally unique identifier in the id attribute.

level: Optional[sigma.schema.RuleLevel]

The level field contains one of five string values. It describes the criticality of a triggered rule.

license: Optional[str]

SPDX License Name

logsource: sigma.schema.RuleLogSource

This section describes the log data on which the detection is meant to be applied to. It describes the log source, the platform, the application and the type that is required in detection.

modified: Optional[Union[sigma.schema.SimpleDate, str]]

The date the rule was last modified. This should be YYYY-MM-DD or YYYY/MM/DD. If the field is not formatted in this way, it will be saved as a simple string.

classmethod parse_obj(obj: Any) sigma.schema.Rule
references: Optional[List[str]]

References to the source that the rule was derived from. These could be blog articles, technical papers, presentations or even tweets.

related: Optional[List[sigma.schema.RuleRelation]]

List of rule IDs and associated relationships to this rule.

status: Optional[sigma.schema.RuleStatus]

Declares the status of the rule.

tags: Optional[List[sigma.schema.RuleTag]]

A Sigma rule can be categorised with tags.

title: str

A brief title for the rule that should contain what the rules is supposed to detect (max. 256 characters).

to_sigma() Dict[str, Any]

Convert this rule back into a JSON-serializable dictionary representing the sigma rule. This dictionary can safely be converted to JSON or YAML and written back to disk as a valid Sigma rule.

transform(transforms: List[sigma.transorms.Transformation]) Rule

Apply all transformations to this rule and all condition expressions

class sigma.schema.RuleDetection(*args, timeframe: sigma.schema.ConstrainedStrValue = None, condition: Union[List[str], str], **kwargs)

Bases: pydantic.main.BaseModel

Defines the detection criteria for this rule including the timeframe, condition specification and any number of detection field lists/keywords grouped by arbitrary names.

class Config

Bases: object

extra = 'allow'
schema_extra = {'examples': [{'timeframe': '5m', 'condition': '(selection1 or selection2) and not filter', 'selection1': {'Imphash': ['a53a02b997935fd8eedcb5f7abab9b9f', 'e96a73c7bf33a464c510ede582318bf2']}, 'selection2': {'CommandLine|endswith': '.exe -S', 'ParentImage|endswith': '\\services.exe'}, 'filter': {'Image|endswith': '\\clussvc.exe'}}]}
GRAMMAR_PARSER: ClassVar[Any] = Forward: 'or' term
condition: Union[List[str], str]
property expression: sigma.grammar.Expression
get_expression(identifier: str) sigma.grammar.Expression

Construct an expression from the specified identifier. If the requested identifier does not exist, a MissingIdentifier exception is raised.

lookup_expression(pattern: str) Generator[str, None, None]

Lookup identifier expressions by a glob pattern

parse_grammar() sigma.grammar.Expression

Parse the condition and evaluate fields to produce a single search expression.

post_init(rule: sigma.schema.Rule)
property rule: sigma.schema.Rule
timeframe: Optional[str]
transform(rule: Rule, transforms: sigma.transform.Transformation)

Transform all expressions with the given transformations

update_expression(expression: sigma.grammar.Expression)
classmethod validate_detection(v)

Validate the schema for the

class sigma.schema.RuleDetectionFields

Bases: Dict[str, Any]

Defines the detection criteria by AND-separated field matching.

build_expression() sigma.grammar.Expression

Build the logical AND expression for these keywords

class sigma.schema.RuleDetectionList(iterable=(), /)

Bases: List[Union[str, sigma.schema.RuleDetectionFields]]

Defines the detection criteria by OR-separated keyword strings.

build_expression() sigma.grammar.Expression

Build the logical OR expression for these keywords

class sigma.schema.RuleLevel(value)

Bases: sigma.schema.LowercaseString, enum.Enum

The level field contains one of five string values. It describes the criticality of a triggered rule. While low and medium level events have an informative character, events with high and critical level should lead to immediate reviews by security analysts.

CRITICAL = 'critical'

Highly relevant event that indicates an incident. Critical events should be reviewed immediately.

HIGH = 'high'

Relevant event that should trigger an internal alert and requires a prompt review.

INFORMATIONAL = 'informational'

Rule is intended for enrichment of events, e.g. by tagging them. No case or alerting should be triggered by such rules because it is expected that a huge amount of events will match these rules.

LOW = 'low'

Notable event but rarely an incident. Low rated events can be relevant in high numbers or combination with others. Immediate reaction shouldn’t be necessary, but a regular review is recommended.

MEDIUM = 'medium'

Relevant event that should be reviewed manually on a more frequent basis.

to_severity() int

Convert the rule level to an integer severity level in the range 0-100

class sigma.schema.RuleLicense

Bases: str

License of the rule according the SPDX ID specification.

class sigma.schema.RuleLogSource(*, category: str = None, product: str = None, service: str = None, definition: str = None, **extra_data: Any)

Bases: pydantic.main.BaseModel

Defines the source of log entries for a sigma rule

class Config

Bases: object

extra = 'allow'
category: Optional[str]
definition: Optional[str]
product: Optional[str]
service: Optional[str]
class sigma.schema.RuleRelation(*, id: uuid.UUID, type: sigma.schema.RuleRelationType)

Bases: pydantic.main.BaseModel

Defines detections/queries for this rule

class Config

Bases: object

schema_extra = {'examples': [{'id': '7aa7009a-28b9-4344-8c1f-159489a390df', 'type': 'derived'}]}
id: uuid.UUID
type: sigma.schema.RuleRelationType
class sigma.schema.RuleRelationType(value)

Bases: sigma.schema.LowercaseString, enum.Enum

Type of rule relationship

DERIVED = 'derived'

Rule was derived from the referred rule or rules, which may remain active.

MERGED = 'merged'

Rule was merged from the referred rules. The rules may be still existing and in use.

OBSOLETES = 'obsoletes'

Rule obsoletes the referred rule or rules, which aren’t used anymore.

RENAMED = 'renamed'

The rule had previously the referred identifier or identifiers but was renamed for any other reason, e.g. from a private naming scheme to UUIDs, to resolve collisions etc. It’s not expected that a rule with this id exists anymore.

class sigma.schema.RuleStatus(value)

Bases: sigma.schema.LowercaseString, enum.Enum

Indicates the development status for a sigma rule

DEPRECATED = 'deprecated'

the rule is replace or cover by another one. The link is made by the related field.

EXPERIMENTAL = 'experimental'

an experimental rule that could lead to false results or be noisy, but could also identify interesting events.

STABLE = 'stable'

the rule is considered as stable and may be used in production systems or dashboards.

TEST = 'test'

an almost stable rule that possibly could require some fine tuning.

TESTING = 'testing'

an almost stable rule that possibly could require some fine tuning.

UNSUPPORTED = 'unsupported'

the rule can not be use in its current state (special correlation log, home-made fields)

class sigma.schema.RuleTag

Bases: str

A Sigma rule can be categorised with tags. Tags should generally follow this syntax:

  • Character set: lower-case letters, underscores and hyphens

  • no spaces

  • Tags are namespaced, the dot is used as separator. e.g. attack.t1234 refers to technique 1234 in the namespace attack; Namespaces may also be nested

  • Keep tags short, e.g. numeric identifiers instead of long sentences

  • If applicable, use predefined tags. Feel free to send pull request or issues with proposals for new tags

Predefined tags: https://github.com/SigmaHQ/sigma/wiki/Tags

property name: str

The name is everything after the first period in the tag. If there are no periods, then the name is an empty string.

property namespace: Optional[str]

The namespace is everything prior to the first period in the tag

classmethod validate(v)
class sigma.schema.Sigma

Bases: object

This class is never instantiated but provides an object-oriented interface to loading sigma documents as a whole, which could include collections of rules bound by correlations and/or an include document which imports other rules from disk.

classmethod load(path: Union[str, os.PathLike]) Union[sigma.schema.Rule, sigma.schema.Correlation, List[Union[sigma.schema.Rule, sigma.schema.Correlation]]]

Load Sigma rules or correlations from the given path. The return value of this function is either a singular sigma rule or a correlation object which represents a list of rules bound by a correlation.

class sigma.schema.SimpleDate

Bases: datetime.date

Simple date class which has a custom parser to handle either YYYY/MM/DD or YYYY-MM-DD

class sigma.schema.TemporalCorrelation(*, action: typing.Literal['correlation'], name: str, rule: typing.Union[str, typing.List[str]], type: typing.Literal[<CorrelationType.TEMPORAL: 'temporal'>], timespan: sigma.schema.ConstrainedStrValue, level: sigma.schema.RuleLevel, **extra_data: typing.Any)

Bases: sigma.schema.BaseCorrelation

type: Literal[<CorrelationType.TEMPORAL: 'temporal'>]

Type of correlation to be used