Common Patterns

Sigma Rule Skeleton

title: <Detection Name>
id: <UUID>
status: experimental
description: <What this detects>
references:
  - <URL or CTI report reference>
author: CTI Analyst
date: 2025/01/01
tags:
  - attack.<tactic>
  - attack.<technique_id>  # e.g. attack.t1053, attack.t1059
logsource:
  category: <process_creation | network_connection | file_event | ...>
  product: <windows | linux | azure>
detection:
  selection:
    FieldName|<modifier>: <value>
  condition: selection
falsepositives:
  - <Known benign scenarios>
level: medium

Generic KQL Query Pattern

TableName
| where ColumnName == "value" or ColumnName contains "partial"
| project TimeGenerated, RelevantColumn1, RelevantColumn2
| take 10

Always discover table names with list_kusto_tables() and column names with get_table_schema(table) before writing queries. Do not assume column names.

Investigation Decision Tree

  • Query returns 0 rows? → Check column names against schema (exact match required) → Broaden filters: contains instead of == → Sample the table to see what values actually exist → Remove time-based filters to test without date constraints
  • Query returns errors? → Verify table name exists via list_kusto_tables() → Check for KQL syntax issues (missing pipes, wrong operators) → For nested/JSON columns, use tostring() to extract values
  • Not sure which table to use? → List all tables, read their schemas, sample a few rows → Let the detection objective and CTI report guide your choice

Common Mistakes to Avoid

  • Skipping CTI reports and going straight to data exploration
  • Guessing column names instead of checking the schema first
  • Writing overly specific queries that return 0 rows
  • Not including MITRE technique IDs in the Sigma rule tags
  • Submitting without calling validate_output_json