Posted by:

David Greenwood

David Greenwood, Chief of Signal

If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly. Please view the post on signalscorps.com for the full interactive viewing experience.

In this post I will dive into how to define conditions to create complex detection criteria for Sigma Rules.

There are a range of conditions that can be defined for detection.

There are currently six Condition Operators that can prove useful in tuning the extensibility and accuracy a rule by describing how the Search Identifiers should be observed.

  1. Exact match
  2. Logical AND/OR
  3. Negation with ‘not’
  4. x of search-identifier
  5. x of them
  6. x of search-identifier-pattern
  7. Brackets (and condition precedence)

1. Single Search Identifier

The most simplest condition, where only one Search Modifier is used;

detection:
  search_identifier_1:
    CommandLine:
      - DumpCreds
      - invoke-mimikatz
  condition: search_identifier_1

Here the condition is that search_identifier_1 must be true to create a detection.

2. Logical AND/OR

This is the most common Condition Operator. Here is an example;

detection:
  search_identifier_1:
    CommandLine|contains:
      - DumpCreds
      - invoke-mimikatz
  search_identifier_2:
    CommandLine|contains:
      - rpc
      - token
  condition: search_identifier_1 and search_identifier_2

In this example, both search_identifier_1 AND search_identifier_2 must be observed.

Describing this example logically; (CommandLine EQUALS DumpCreds OR CommandLine EQUALS invoke-mimikatz) AND (CommandLine EQUALS rpc OR CommandLine EQUALS token).

OR Operators are written in the same way;

detection:
  search_identifier_1:
    CommandLine|contains:
      - DumpCreds
      - invoke-mimikatz
  search_identifier_2:
    CommandLine|contains:
      - rpc
      - token
  condition: search_identifier_1 or search_identifier_2

Describing this example logically; (CommandLine EQUALS DumpCreds OR CommandLine EQUALS invoke-mimikatz) OR (CommandLine EQUALS rpc OR CommandLine EQUALS token).

3. Negation with ‘not’

Conditions can be especially useful for filtering use-cases which is where the not operator comes in handy. Take this example;

detection:
  search_identifier_1:
     EventID: 4738
  search_identifier_2:
     PasswordLastSet: null
  condition: search_identifier_1 and not search_identifier_2

Here I am using the and not condition to say the log line must contain EventID EQUALS 4738 but not PasswordLastSet EQUALS null.

4. x of Search Identifier

This Condition type can be very useful in overriding the default behaviour of a Lists (where items are considered with OR operators).

detection:
  search_identifier_1|contains:
  - EVILSERVICE
  - svchost.exe -n evil
  search_identifier_2|contains:
  - token
  - rpc
  - crypto
condition: 2 of search_identifier_1 and search_identifier_2

Here the condition is overriding the default List behaviour for search_identifier_1. Logically this condition requires that the log line contains the strings; (EVILSERVICE AND svchost.exe -n evil) AND (token OR rpc OR crypto).

You can also use all instead of an integer when specifying x of, like so;

detection:
  search_identifier_1:
  - EVILSERVICE
  - svchost.exe -n evil
  search_identifier_2:
  - token
  - rpc
  - crypto
condition: all of search_identifier_1 and 2 of search_identifier_2

Now all strings defined in search_identifier_1 as well as at least 2 strings defined in search_identifier_2 must be present in the log line to create a detection.

5. x of them

Instead of defining a specific Search Identifier, you can categorise all Search Identifiers as them in the condition, like so;

detection:
  search_identifier_1:
    CommandLine|contains:
      - DumpCreds
      - invoke-mimikatz
  search_identifier_2:
    CommandLine|contains:
      - rpc
      - token
      - crypto
  search_identifier_3:
    CommandLine|contains:
      - bitcoin
  condition: 1 of them

In this example, 1 of the Search Identifiers defined in the rule (search_identifier_1 OR search_identifier_2 OR search_identifier_3) must be true.

Like before, x can be defined using all like so;

  condition: all of them

That said, I would discourage the use of all of them where possible as it prevents the possibility of downstream users of a rule to generically filter unwanted matches.

Instead, I would use the Search Identifier Pattern instead. Speaking of that Condition…

6. x of Search Identifier Pattern

This is very similar to the previous Condition but is a bit more flexible because it can be used to match search identifiers using wildcards (*).

Here I am matching all the Search Identifiers;

detection:
  search_identifier_1:
    CommandLine|contains:
      - DumpCreds
      - invoke-mimikatz
  search_identifier_2:
    CommandLine|contains:
      - rpc
      - token
      - crypto
  search_identifier_3:
    CommandLine|contains:
      - bitcoin
  condition: all of search_identifier_*

Here the Condition matches on any Search Identifier starting with search_identifier_.

This Condition Type can be useful for filtering;

detection:
  search_identifier_1:
    CommandLine|contains:
      - DumpCreds
      - invoke-mimikatz
  search_identifier_2:
    CommandLine|contains:
      - rpc
      - token
      - crypto
  log_filter_1:
     PasswordLastSet: null
  log_filter_2:
     Username: null
  condition: 1 of search_identifier_* and not 1 of log_filter_*

Here I am also using the and not operator, with two Search Identifier Patterns – the benefit being I do not need to explicitly define all three Search Identifiers individually.

In this case at least 1 search_identifier_ must be true and not 1 of log_filter must be true.

7. Brackets (and condition precedence)

As condition need to become more complex, using brackets (parenthesis) can offer additional options to the other Condition options specified.

detection:
  search_identifier_1:
    CommandLine|contains:
      - DumpCreds
      - invoke-mimikatz
  search_identifier_2:
    CommandLine|contains:
      - rpc
      - token
      - crypto
  search_identifier_3:
    CommandLine|contains:
      - bitcoin
  condition: (search_identifier_1 and search_identifier_2) or (search_identifier_2 and search_identifier_3) and not (search_identifier_1 and search_identifier_3)

In this example, any combination except for search_identifier_1 and search_identifier_3 being seen in the same log line will trigger a detection.

Bracket are considered with the highest order of operation. Here is the full Sigma order of operation from most to least binding;

  1. ()
  2. x of y
  3. not
  4. and
  5. or
  6. |

Dealing with detetctions

Now that a rule is being used, it is only a matter of time before it triggers a detection. When that happens, the analyst handling the detection event might want to start a deeper investigation.

The fields attribute inside a Sigma Rule can help an analyst decide the next steps by defining a log fields that could be interesting in further analysis of the event.

fields:
  - CommandLine
  - ParentCommandLine

Dealing with false positive detections

Once you deploy a rule to one of your security tools analysts will also start to discover some incorrect detections.

These false positive alerts can be dealt with in 2 ways:

  1. Update the rule with a more highly tuned detection. However, that is not always possible,
  2. Update the rule with falsepositive attributes information

The falsepositive field can be used to describe a List of known false positives which can occur from a detection. Here is an example,

falsepositives:
  - PIM (Privileged Identity Management) generates this event each time 'eligible role' is enabled.
  - Legitimate administration activities

Similar to the fields attribute, when triggered this falsepositives information inside the rule can help an analyst triaging alerts as to how they proceed (or if they follow up on it at all).

Note, you will also see some Sigma Rules define falsepositive Search Identifiers. Here is an example of that;

detection:
  selection:
    - 'rm /var/log/syslog'
    - 'rm -r /var/log/syslog'
    - 'rm -f /var/log/syslog'
    - 'rm -rf /var/log/syslog'
    - 'mv /var/log/syslog'
    - ' >/var/log/syslog'
    - ' > /var/log/syslog'
  falsepositives:
    - '/syslog.'
  condition: selection and not falsepositives
falsepositives:
  - Log rotation

Generally I would advise naming Search Identifiers as falsepositives but it is possible.

In this case, the condition is accounting for potential False Positives, but also in the falsepositives attribute describes how potential false positive detections could occur (Log rotation).

Conversion of Sigma Rules

You now have a good foundation on what is required to write a good Sigma Rule.

The main reason to use Sigma is that rules can be converted (sometimes referred to as translated) into other detection languages, like Google’s YARA-L, Splunk SPL or Kusto used by Microsoft Sentinel.

In the next part of the tutorial I will introduce these languagues to help set the foundations for the final part of this tutorial where I will talk about the conversion pipeline of a Sigma Rule into these (and other) target formats.


Sigma Certification (Virtual and In Person)

The content used in this post is a small subset of our full training material used in our Sigma training.

If you want to join a select group of certified Sigma professionals, subscribe to our newsletter below to be notified of new course dates.




Discuss this post


Signals Corps Slack

Never miss an update


Sign up to receive new articles in your inbox as they published.