Chapter 216

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.

Scenario

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

PYRAMID OF PAIN (attacker perspective = detection engineer's value hierarchy) ═══════════════════════════════════════════════════════════════════════ ▲ [TTPs] │ Hardest to change → most valuable detection [Tools] │ [Network/Host Artifacts] [Domain Names] [IP Addresses] [Hash Values] │ Easiest to change → low detection value ▼ DETECTION STRATEGY: Focus detection at TTP level (T1003, T1059, etc.). IOC-based detections (hash, IP) expire in hours when attacker rotates infrastructure. TTP-based detections survive tool changes, infrastructure rotation, and operator skill variations. THREAT MODEL → DETECTION MAPPING: 1. List attacker goals in your environment (DA creds, PII, IP) 2. Identify most likely techniques to reach each goal (ATT&CK) 3. For each technique: identify required telemetry source 4. Assess telemetry availability vs. coverage gap 5. Prioritize rules by: impact × likelihood × telemetry availability ═══════════════════════════════════════════════════════════════════════

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 sourceIdentificationTuning approach
Legitimate admin tooling (SCCM, Tanium)Baseline: top processes accessing lsassAdd to filter_legitimate by Image path + version
AV/EDR opening lsass for scanSourceImage = vendor processAllowlist vendor process names + signature paths
Developer builds triggering detectionDeviceName matches dev workstation OUScope rule to production / server OUs only
Crash dump tools (WerFault)SourceImage contains WerFault or Windows Error ReportingAdd to base filter; these only fire on crash
Scheduled scans producing periodic spikesTime-pattern: every day at 02:00Rate 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.