detection engineering

Building Detection Rules That Actually Fire: A Sigma Rule Development Guide

Sandeep Karnik
March 14, 2026 · 8 min read

The Detection Gap

Most organizations have logs. Most have a SIEM. What most don't have is detection content that fires on real attacks. The gap isn't data collection - it's detection engineering.

Sigma is the open standard that closes this gap. It lets you write detection rules once and convert them to any SIEM query language - Splunk SPL, Elastic KQL, Microsoft Sentinel KQL, QRadar AQL, and dozens more. Think of it as YARA for logs.

This guide walks through writing Sigma rules that are precise enough to catch attacks and quiet enough to not drown your SOC in false positives.

Sigma Rule Anatomy

Every Sigma rule is a YAML file with a defined structure:

title: Suspicious PowerShell Download Cradle
	id: 3b6ab547-1298-4a74-8f80-6a42df234567
	status: experimental
	description: |
	    Detects PowerShell commands using common download cradle patterns
	    such as Net.WebClient, Invoke-WebRequest, or Start-BitsTransfer.
	references:
	    - https://attack.mitre.org/techniques/T1059/001/
	author: Palavi Tech
	date: 2026/03/28
	tags:
	    - attack.execution
	    - attack.t1059.001
	logsource:
	    category: process_creation
	    product: windows
	detection:
	    selection_parent:
	        ParentImage|endswith:
	            - '\cmd.exe'
	            - '\explorer.exe'
	    selection_powershell:
	        Image|endswith: '\powershell.exe'
	        CommandLine|contains:
	            - 'Net.WebClient'
	            - 'Invoke-WebRequest'
	            - 'IWR '
	            - 'Start-BitsTransfer'
	            - 'DownloadFile'
	            - 'DownloadString'
	    condition: selection_parent and selection_powershell
	falsepositives:
	    - Legitimate software installers using PowerShell download
	    - SCCM or Intune deployment scripts
	level: medium

Key Fields Explained

FieldPurpose
titleHuman-readable name - shows up in alerts
idUnique UUID - used for rule tracking and correlation
statusexperimental, test, or stable - signals confidence level
logsourceDefines which log data the rule applies to
detectionThe actual logic - selections and conditions
levelSeverity: informational, low, medium, high, critical
falsepositivesKnown FP scenarios - helps analysts triage
tagsMITRE ATT&CK tags for framework mapping

The Log Source: Getting It Right

The logsource field is where most beginners make mistakes. It's not just metadata - it determines which log pipeline the rule targets.

Common Log Sources

# Windows process creation (Sysmon Event ID 1 or Security 4688)
	logsource:
	    category: process_creation
	    product: windows

	# Windows PowerShell script block logging
	logsource:
	    product: windows
	    service: powershell-scriptblock

	# Windows Security event log
	logsource:
	    product: windows
	    service: security

	# Web proxy / firewall logs
	logsource:
	    category: proxy

	# DNS query logs
	logsource:
	    category: dns

Pro tip: Always prefer category over service when possible. Categories are SIEM-agnostic - the Sigma converter maps them to the correct event source for each backend. Service names are backend-specific and reduce portability.

Detection Logic: Selections and Conditions

The detection block is where the rule's precision lives. Understanding how selections compose is critical.

Selection Basics

A selection is a named set of field-value matches. Within a single selection, multiple values for the same field are OR'd, while different fields are AND'd:

detection:
	    selection:
	        Image|endswith: '\cmd.exe'        # AND
	        CommandLine|contains:
	            - '/c whoami'                 # OR
	            - '/c ipconfig'               # OR
	            - '/c net user'               # OR
	    condition: selection

This fires when cmd.exe runs with a command line containing any of those recon commands.

Combining Multiple Selections

Multiple named selections let you build complex logic:

detection:
	    selection_process:
	        Image|endswith: '\rundll32.exe'
	    selection_suspicious:
	        CommandLine|contains:
	            - 'javascript:'
	            - 'vbscript:'
	            - 'shell32.dll,Control_RunDLL'
	    filter_legitimate:
	        CommandLine|contains: 'desk.cpl'
	        ParentImage|endswith: '\explorer.exe'
	    condition: selection_process and selection_suspicious and not filter_legitimate

This catches suspicious rundll32.exe usage while filtering out the legitimate desktop settings invocation.

Modifier Reference

Modifiers transform how field values are matched:

ModifierBehaviorExample
containsSubstring matchCommandLine|contains: '-enc'
endswithSuffix matchImage|endswith: '\powershell.exe'
startswithPrefix matchTargetFilename|startswith: 'C:\Temp\'
reRegular expressionCommandLine|re: '\\\\[0-9]{1,3}\\.'
allAll values must match (AND instead of OR)CommandLine|contains|all:
base64Match base64-encoded variantsCommandLine|base64: 'IEX'
cidrIP range matchingSourceIP|cidr: '10.0.0.0/8'

Five Rules Every SOC Should Deploy

Rule 1: LSASS Memory Access (Credential Dumping)

title: LSASS Memory Access via Process Handle
	id: 8a5e3b2c-7d41-4f89-b123-456789abcdef
	status: stable
	description: |
	    Detects processes opening a handle to LSASS with memory read access,
	    a technique used by Mimikatz, ProcDump, and other credential dumpers.
	author: Palavi Tech
	date: 2026/03/28
	tags:
	    - attack.credential_access
	    - attack.t1003.001
	logsource:
	    category: process_access
	    product: windows
	detection:
	    selection:
	        TargetImage|endswith: '\lsass.exe'
	        GrantedAccess|contains:
	            - '0x1010'
	            - '0x1410'
	            - '0x1438'
	            - '0x143a'
	    filter_system:
	        SourceImage|startswith:
	            - 'C:\Windows\System32\'
	            - 'C:\Program Files\Windows Defender\'
	            - 'C:\ProgramData\Microsoft\Windows Defender\'
	    condition: selection and not filter_system
	falsepositives:
	    - Legitimate EDR/AV products accessing LSASS
	    - Windows Error Reporting
	level: high

Why it matters: LSASS contains plaintext passwords, NTLM hashes, and Kerberos tickets. Any unexpected access is a critical signal.

Rule 2: Scheduled Task via Command Line (Persistence)

title: Scheduled Task Created via schtasks.exe
	id: 9b6f4c3d-8e52-5a90-c234-567890bcdef0
	status: stable
	description: |
	    Detects the creation of scheduled tasks via schtasks.exe,
	    commonly used for persistence or lateral movement.
	author: Palavi Tech
	date: 2026/03/28
	tags:
	    - attack.persistence
	    - attack.t1053.005
	logsource:
	    category: process_creation
	    product: windows
	detection:
	    selection:
	        Image|endswith: '\schtasks.exe'
	        CommandLine|contains|all:
	            - '/create'
	    selection_suspicious:
	        CommandLine|contains:
	            - '/sc onlogon'
	            - '/sc onidle'
	            - '/sc onstart'
	            - 'powershell'
	            - 'cmd.exe /c'
	            - 'mshta'
	            - 'rundll32'
	            - 'regsvr32'
	            - '\AppData\'
	            - '\Temp\'
	            - '\ProgramData\'
	    condition: selection and selection_suspicious
	falsepositives:
	    - IT automation scripts creating legitimate scheduled tasks
	    - Software installation routines
	level: medium

Rule 3: DCSync Detection

title: Directory Service Replication from Non-DC Host
	id: ac7g5d4e-9f63-6b01-d345-678901cdef12
	status: stable
	description: |
	    Detects directory replication requests (DCSync) originating from
	    machines that are not domain controllers, indicating credential theft.
	author: Palavi Tech
	date: 2026/03/28
	tags:
	    - attack.credential_access
	    - attack.t1003.006
	logsource:
	    product: windows
	    service: security
	detection:
	    selection:
	        EventID: 4662
	        Properties|contains:
	            - '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2'
	            - '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'
	    filter_dc:
	        SubjectUserName|endswith: '$'
	        SubjectUserName|contains:
	            - 'DC01'
	            - 'DC02'
	    condition: selection and not filter_dc
	falsepositives:
	    - Azure AD Connect synchronization
	level: critical

Tuning note: Replace the DC name filter with your actual DC hostnames. This is the most environment-specific rule - get it right and it's one of the highest-fidelity detections you can deploy.

Rule 4: Suspicious DNS Query (C2 Beaconing)

title: DNS Query to Newly Registered or Suspicious TLD
	id: bd8h6e5f-0a74-7c12-e456-789012def345
	status: experimental
	description: |
	    Detects DNS queries to TLDs and patterns commonly associated
	    with malware C2 infrastructure.
	author: Palavi Tech
	date: 2026/03/28
	tags:
	    - attack.command_and_control
	    - attack.t1071.004
	logsource:
	    category: dns
	detection:
	    selection_tld:
	        query|endswith:
	            - '.top'
	            - '.xyz'
	            - '.club'
	            - '.work'
	            - '.click'
	            - '.surf'
	            - '.rest'
	    selection_pattern:
	        query|re: '^[a-z0-9]{16,}\.'
	    condition: selection_tld or selection_pattern
	falsepositives:
	    - Legitimate websites on uncommon TLDs
	    - CDN subdomains with hash-based names
	level: low

Rule 5: Kerberoasting Detection

title: Kerberos Service Ticket Request with RC4 Encryption
	id: ce9i7f6a-1b85-8d23-f567-890123efa456
	status: stable
	description: |
	    Detects Kerberos TGS requests using RC4 encryption, which may
	    indicate Kerberoasting activity targeting service account credentials.
	author: Palavi Tech
	date: 2026/03/28
	tags:
	    - attack.credential_access
	    - attack.t1558.003
	logsource:
	    product: windows
	    service: security
	detection:
	    selection:
	        EventID: 4769
	        TicketEncryptionType: '0x17'
	        Status: '0x0'
	    filter_machine:
	        ServiceName|endswith: '$'
	    filter_krbtgt:
	        ServiceName: 'krbtgt'
	    condition: selection and not filter_machine and not filter_krbtgt
	falsepositives:
	    - Legacy systems that only support RC4 encryption
	    - Environments that haven't migrated to AES
	level: high

Converting Sigma to Your SIEM

Sigma rules are SIEM-agnostic - you need a converter to transform them into your platform's query language.

Using sigma-cli

# Install
	pip install sigma-cli pySigma-backend-splunk pySigma-pipelines-sysmon

	# Convert to Splunk SPL
	sigma convert -t splunk -p sysmon rule.yml

	# Convert to Elastic/Lucene
	sigma convert -t elasticsearch-lucene -p ecs_windows rule.yml

	# Convert to Microsoft Sentinel KQL
	sigma convert -t microsoft365defender rule.yml

Example Conversion

The LSASS access rule converted to Splunk:

index=sysmon EventCode=10
	TargetImage="*\\lsass.exe"
	(GrantedAccess="*0x1010*" OR GrantedAccess="*0x1410*"
	 OR GrantedAccess="*0x1438*" OR GrantedAccess="*0x143a*")
	NOT (SourceImage="C:\\Windows\\System32\\*"
	     OR SourceImage="C:\\Program Files\\Windows Defender\\*")

And the same rule in Elastic KQL:

event.code: "10" AND winlog.event_data.TargetImage: *\\lsass.exe
	AND winlog.event_data.GrantedAccess: (*0x1010* OR *0x1410* OR *0x1438* OR *0x143a*)
	AND NOT winlog.event_data.SourceImage: (C\:\\Windows\\System32\\* OR C\:\\Program\ Files\\Windows\ Defender\\*)

Reducing False Positives

The difference between a rule that works and a rule that gets disabled is tuning. Here's a systematic approach:

Step 1: Deploy in Audit Mode

Run the rule for 1-2 weeks without triggering alerts. Log the matches and review them:

# Set level to informational during tuning
	level: informational
	status: experimental

Step 2: Analyze the Noise

For each false positive, ask:

  • Is it a known-good process? Add it to the filter section
  • Is it a known-good parent process? Filter by ParentImage
  • Is it only from specific machines? Filter by ComputerName (but document why)
  • Is the rule too broad? Tighten the selection modifiers

Step 3: Build Environment-Specific Filters

detection:
	    selection:
	        # ... attack detection logic ...
	    filter_sccm:
	        ParentImage|endswith: '\ccmexec.exe'
	    filter_monitoring:
	        SourceImage|contains:
	            - '\CrowdStrike\'
	            - '\SentinelOne\'
	            - '\Tanium\'
	    condition: selection and not 1 of filter_*

Step 4: Promote to Production

Once the rule fires only on true positives (or near-true positives with known, documented FP scenarios), promote it:

status: stable
	level: high    # or whatever severity is appropriate

Testing Your Rules

Before deploying to production, validate against known-bad activity:

Atomic Red Team

# Install
	Install-Module -Name AtomicRedTeam

	# Run the T1003.001 test (LSASS credential dumping)
	Invoke-AtomicTest T1003.001 -TestNumbers 1

	# Verify your LSASS access rule fires

Manual Validation

For each rule, create a test case document:

test:
	  rule: LSASS Memory Access via Process Handle
	  steps:
	    - Run: procdump.exe -ma lsass.exe lsass.dmp
	    - Expected: Alert fires within 60 seconds
	    - Fields to verify:
	        - SourceImage contains procdump
	        - TargetImage contains lsass
	        - GrantedAccess matches selection
	  cleanup:
	    - Delete lsass.dmp
	    - Confirm no residual artifacts

Organizing a Detection Rule Library

As your rule set grows, structure matters:

sigma-rules/
	├── credential_access/
	│   ├── lsass_memory_access.yml
	│   ├── dcsync_detection.yml
	│   └── kerberoasting_rc4.yml
	├── persistence/
	│   ├── scheduled_task_creation.yml
	│   └── registry_run_key.yml
	├── command_and_control/
	│   ├── suspicious_dns_tld.yml
	│   └── beaconing_pattern.yml
	├── execution/
	│   └── powershell_download_cradle.yml
	└── README.md

Track rules in version control. Every change should be a commit with context - what broke, what was tuned, what FP was eliminated.

Key Takeaways

  1. Write rules for behaviors, not indicators. IOC-based rules go stale in days. Behavioral rules (process accessing LSASS, RC4 Kerberos tickets) catch variants for years.

  2. The falsepositives field is not optional. If you can't list known FPs, you haven't tested the rule. This field saves your SOC analysts hours of triage.

  3. Start with five high-fidelity rules, not fifty noisy ones. A SOC that trusts its alerts investigates faster than one drowning in noise.

  4. Test every rule against Atomic Red Team before production. A rule that doesn't fire on known-bad is worse than no rule - it gives false confidence.

  5. Sigma is a starting point, not an endpoint. Convert, test, tune for your environment, and document every filter. The generic rule is 60% of the work - the last 40% is what makes it production-ready.


Good detections are tuned, not just written. More hands-on security walkthroughs on the BytesCop blog.

Display Mode
Direction Mode
Theme Color
Theme Cover