Detection Engineering Methodology
Detection engineering is the practice of systematically converting threat knowledge into detection logic. Unlike reactive alert writing (which produces one rule per IOC), detection engineering produces threat-model-driven coverage that detects attack techniques regardless of the specific tooling used. The output is a portfolio of rules anchored to the MITRE ATT&CK framework with known false positive rates, verified against production telemetry, and maintained through adversary simulation testing.
Your team is asked to improve detection coverage for the credential access tactic (TA0006). You have Sysmon, MDE, and Sentinel/Splunk access. Build a detection program: threat model the tactic, identify the highest-value telemetry sources, write Sigma rules for the top techniques, implement KQL queries in MDE, and define the testing methodology to verify coverage without deploying actual malware in production.
The Detection Pyramid
Sigma Rule Crafting
# Full Sigma rule template with all sections:
title: LSASS Process Memory Access by Non-System Process
id: a3a5b2a0-1234-5678-9abc-def012345678
status: production
description: Detects process access to lsass.exe with read access rights consistent with credential dumping tools.
references:
- https://attack.mitre.org/techniques/T1003/001/
author: Detection Engineering Team
date: 2025/01/01
modified: 2026/09/01
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 10
TargetImage|endswith: '\lsass.exe'
GrantedAccess|contains:
- '0x1010'
- '0x1410'
- '0x1438'
- '0x143a'
- '0x1fffff'
filter_legitimate:
SourceImage|contains:
- '\MsMpEng.exe'
- '\csrss.exe'
- '\werfault.exe'
- '\WerFaultSecure.exe'
- '\taskmgr.exe'
# Add site-specific legitimate processes after baseline analysis
condition: selection and not filter_legitimate
falsepositives:
- EDR agents that open lsass for memory scanning (add to filter after baseline)
- Some crash dump utilities
level: high
tags:
- attack.credential_access
- attack.t1003.001
# Sigma condition operators reference:
# selection → match all conditions in block
# not filter → exclude matches
# selection | count() by X > N → aggregation (rate-based rule)
# selection | near other_event → temporal proximity (near operator)
# 1 of selection* → match any of selection1, selection2, ...
# all of them → all blocks match
KQL Hunting Queries
// KQL hunting query structure — iterative refinement pattern:
// STEP 1: Broad sweep (high recall, low precision)
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has_any ("Invoke-Mimikatz", "sekurlsa", "lsadump")
| project Timestamp, DeviceName, AccountName, ProcessCommandLine
// STEP 2: Add behavioral context (frequency baseline)
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine matches regex @"-[Ee][Nn][Cc][Oo]?[Dd]?[Ee]?[Dd]?\s+[A-Za-z0-9+/]{100,}"
| summarize count() by DeviceName, AccountName, bin(Timestamp, 1h)
| where count_ > 3
// STEP 3: Correlate with other events (join pattern)
let lsass_access = DeviceEvents
| where ActionType == "OpenProcessApiCall"
| where FileName =~ "lsass.exe"
| project DeviceName, lsass_time=Timestamp, AccessorProcess=InitiatingProcessFileName;
let network_out = DeviceNetworkEvents
| where RemotePort != 443 and RemotePort != 80 and RemotePort != 53
| where InitiatingProcessFileName !in~ ("svchost.exe","MsMpEng.exe")
| project DeviceName, net_time=Timestamp, DestIP=RemoteIP, DestPort=RemotePort;
lsass_access
| join kind=inner network_out on DeviceName
| where abs(datetime_diff('minute', lsass_time, net_time)) < 5
| project DeviceName, lsass_time, net_time, AccessorProcess, DestIP, DestPort
// STEP 4: Convert high-confidence query to scheduled analytic rule
// In Sentinel: Analytics → Scheduled → paste KQL → set frequency + lookback
Rule Tuning and FP Reduction
| FP source | Identification | Tuning approach |
|---|---|---|
| Legitimate admin tooling (SCCM, Tanium) | Baseline: top processes accessing lsass | Add to filter_legitimate by Image path + version |
| AV/EDR opening lsass for scan | SourceImage = vendor process | Allowlist vendor process names + signature paths |
| Developer builds triggering detection | DeviceName matches dev workstation OU | Scope rule to production / server OUs only |
| Crash dump tools (WerFault) | SourceImage contains WerFault or Windows Error Reporting | Add to base filter; these only fire on crash |
| Scheduled scans producing periodic spikes | Time-pattern: every day at 02:00 | Rate limit or schedule-aware filter |
MITRE Coverage Mapping
# DeTT&CT (Detection Techniques & Coverage Tool) YAML format:
# Maps Sigma rules to MITRE ATT&CK techniques for gap analysis
techniques:
- technique_id: T1003.001 # LSASS Memory
technique_name: LSASS Memory
detection_coverage: 80
# 80% = we detect 4 of 5 known sub-variants; Nanodump still evades
data_sources:
- Sysmon ProcessAccess (EID 10)
- MDE OpenProcessApiCall
rules:
- sigma/lsass_memory_access.yml
- sigma/mimikatz_commandline.yml
gaps:
- PPL-protected LSASS bypass
- Kernel-mode credential dump (no EID 10 generated)
- technique_id: T1558.003 # Kerberoasting
detection_coverage: 90
data_sources:
- Security EID 4769 (TGS-REQ)
rules:
- sigma/kerberoasting_rc4.yml
gaps:
- AES Kerberoasting (lower detection — no RC4 signal)
# Run DeTT&CT: dettectinator -t "T1003.001" → generates ATT&CK Navigator JSON
# Upload to https://mitre-attack.github.io/attack-navigator for visual heatmap
Q&A
Detection engineers frequently debate "high-fidelity, low-coverage" rules versus "low-fidelity, high-coverage" rules. What does the Pyramid of Pain tell us about which layer each type should target, and how do you operationalize a program that contains both types without alert fatigue?
The Pyramid of Pain organizes indicators by how difficult they are for an attacker to change. Hash values and IP addresses are at the base — trivially changed, so IOC-level detections have a short useful life but near-zero false positives when they fire. TTPs (tactics, techniques, procedures) are at the apex — to evade a TTP-based detection, the attacker must fundamentally change their behavior, which costs time and expertise. The pyramid implies that the highest-return detection investment is at the TTP level, but TTP-based rules are inherently broader and produce more false positives because the behaviors they match (process injection, credential dumping, scheduled task creation) are also performed by legitimate software.
The operational answer is to run both layers in parallel but treat their outputs differently. IOC-based detections (hash matches, known bad IPs, specific mutex names) should trigger immediate high-priority alerts with automated blocking because false positive rate is near zero and the window to act is short. TTP-based detections should trigger lower-priority alerts that go into a triage queue rather than a direct incident queue, and analysts should have enrichment context (is this asset a developer machine? is there a change management ticket?) to make the determination quickly. The key operational mechanism is a risk score model: TTP alerts alone score medium; TTP alert + anomalous time/location + first-seen behavior combination scores high. The combination of stacked TTP signals — Kerberoasting + lateral movement + new service creation, all in the same 30-minute window from the same source host — triggers an automated incident ticket regardless of each individual rule's standalone false positive rate. This is the UEBA (User and Entity Behavior Analytics) approach: single events are low confidence, but behavioral chains are high confidence.