Security Operations Center Architecture
A mature SOC is not just an alert queue and a SIEM — it is a data engineering platform, a detection-as-code CI/CD pipeline, a response orchestration layer, and a threat intelligence fusion cell. Detection engineers sit at the intersection of all of these, responsible for translating adversary tradecraft into rules, validating coverage, and reducing analyst toil through automation.
Your SOC is generating 50,000 alerts per day; analysts are triaging 2% of them and marking 95% of those as false positives. Mean time to detect (MTTD) is 14 days. Leadership wants MTTD under 48 hours. Your task: redesign the detection pipeline, implement tiered alerting, build SOAR playbooks for the top 5 alert types, and establish a coverage measurement framework.
SOC Tiers and Detection Engineering Role
Data Pipeline — What Gets Logged and Why
| Log source | Key events | ATT&CK coverage | Retention priority |
|---|---|---|---|
| Windows Security (4xxx) | 4624/4625 logon, 4688 process, 4698/4702 task, 4720 user create | TA0001, TA0003, TA0008 | Critical — 1 year minimum |
| Sysmon (1/3/7/8/10/12/17) | Process create, network, image load, remote thread, reg, pipe | Broadest coverage across all tactics | Critical — enables behavioral rules |
| EDR telemetry (MDE/CrowdStrike) | Process tree, network, file, registry — raw and enriched | Near-complete coverage with behavioral AI | Critical — usually 30d hot, 1y cold |
| DNS query logs | Query, response, NXDOMAIN, rare TLDs | TA0011 (C2), TA0010 (exfil via DNS) | High — enable DGA/tunnel detection |
| Proxy/web gateway | URL, user-agent, response code, bytes | TA0011 (HTTP C2), TA0010 | High |
| NetFlow/IPFIX | Src/dst IP, port, bytes, duration | TA0008 (lateral), TA0010 (exfil) | Medium — good for beaconing; lossy |
| AD/LDAP audit | User/group changes, GPO mods, trust changes | TA0003 (persistence), TA0004 (privesc) | High — tracks AD attack chain |
SIEM Tuning — Alert Quality Over Volume
-- KQL example: tuning a noisy rule by scoping with context and baselined exceptions
-- BAD (generates 4000 alerts/day): "any PowerShell with -enc"
DeviceProcessEvents
| where ProcessCommandLine has "-enc"
-- BETTER: encoded command from non-whitelisted parent, pointing to rare hosts
let management_hosts = dynamic(["SCCM-SRV01","PATCHING-SRV02"]);
DeviceProcessEvents
| where ProcessCommandLine has "-enc"
| where InitiatingProcessFileName !in~ (
"svchost.exe", "services.exe", "WmiPrvSE.exe"
)
| where not (DeviceName has_any (management_hosts))
| extend b64 = extract(@"-[eE][nN][cC][oO]?\s+([A-Za-z0-9+/=]+)", 1, ProcessCommandLine)
| extend decoded = base64_decode_tostring(b64)
| where decoded has_any ("IEX","Invoke-Expression","DownloadString","WebClient","bypass")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName,
ProcessCommandLine, decoded
-- Alert deduplication: suppress repeated identical alert on same host within 1 hour
-- (implement via SOAR dedup logic or SIEM lookup table keyed on host+rule_id+hour bucket)
SOAR Playbook — Automated Alert Enrichment
# SOAR pseudo-playbook: IP IOC triage (runs on every network-based alert)
def ip_triage_playbook(alert):
ip = alert['remote_ip']
# Step 1: Threat intel lookup (VirusTotal, Shodan, AbuseIPDB)
vt = vt_lookup(ip)
abuse = abuseipdb_lookup(ip)
shodan = shodan_lookup(ip)
# Step 2: Internal context
asset_info = cmdb_lookup(alert['hostname'])
user_history = get_user_login_history(alert['user'], days=30)
similar_alerts = siem_count_similar(ip=ip, hours=24)
# Step 3: Scoring
score = 0
if vt['malicious'] > 3: score += 40
if abuse['confidence'] > 80: score += 30
if shodan['org'] in BULLETPROOF_HOSTERS: score += 20
if asset_info['is_privileged']: score += 10
# Step 4: Auto-triage decision
if score >= 70:
create_p1_incident(alert, enrichment={'vt': vt, 'abuse': abuse})
block_ip_on_firewall(ip) # automated containment
notify_oncall()
elif score >= 40:
create_p2_ticket(alert, enrichment={...})
else:
auto_close(alert, reason="low-score after enrichment")
SOC Metrics — What to Measure
| Metric | Target | What it measures |
|---|---|---|
| Mean Time to Detect (MTTD) | < 48 hours (mature: < 1 hour) | Detection pipeline latency |
| Mean Time to Respond (MTTR) | < 4 hours critical, < 24h P2 | Response process efficiency |
| Alert-to-incident ratio | < 10:1 (alert fatigue indicator) | Detection precision (high ratio = FP problem) |
| ATT&CK technique coverage % | > 60% (Tier 3 target: 80%+) | Detection breadth across kill chain |
| Rule FP rate per rule | < 5% per rule | Per-rule quality; drives tuning priority |
| Detection Engineer rule rate | 2-4 rules/week/DE | Detection program velocity |
Detection Engineering
title: SOAR Enrichment Bypass — Direct Alert Close Without Investigation
description: >
Detects when a SOAR playbook closes a high-severity alert without creating
a ticket — may indicate playbook logic error or manipulation.
logsource:
product: soar
service: audit
detection:
selection:
action: 'close_alert'
original_severity: 'high'
ticket_created: false
condition: selection
level: high
-- MDE KQL: ATT&CK coverage gap identification — technique with no recent alerts
-- (conceptual: join your rule catalog against alert fire history to find dark areas)
let rule_catalog = datatable(technique_id:string, rule_name:string)[
"T1003.001", "LSASS Memory Access",
"T1055.001", "DLL Injection",
"T1071.001", "HTTP C2 Beaconing",
"T1021.002", "SMB Lateral Movement"
];
let fired_last_30d = AlertInfo
| where Timestamp > ago(30d)
| summarize last_fired=max(Timestamp) by AttackTechniques
| mv-expand AttackTechniques to typeof(string);
rule_catalog
| join kind=leftouter fired_last_30d on $left.technique_id == $right.AttackTechniques
| where isnull(last_fired) or last_fired < ago(14d)
| project technique_id, rule_name, last_fired
| order by last_fired asc
Q&A
A SOC has a high alert volume problem — 50,000 alerts per day with analysts manually triaging all of them. What is the detection engineering approach to sustainably reducing alert volume without increasing missed detections, and how do you prevent the "whack-a-mole" pattern where tuning one rule creates new FPs in adjacent rules?
The root cause of high-volume, low-fidelity alerts is almost always rules written at the wrong level of specificity: broad signatures that match behavior patterns shared between legitimate and malicious activity. The detection engineering approach starts with per-rule false-positive measurement — classify each alert (true positive, false positive, benign true positive) and compute an FP rate per rule over 30 days. Rules with FP rates above 20% are candidates for immediate tuning or retirement. The tuning priority list typically reveals a small number of "noisy rules" (top 10 rules often generate 80%+ of volume) that can be narrowed with additional behavioral context — parent process, command-line pattern, asset class, time window — without losing true-positive coverage. This is the safe path: surgical per-rule tuning with documented rationale.
The whack-a-mole pattern emerges when tuning is done by adding exceptions to existing rules rather than rewriting the detection logic. Suppressing "any PowerShell with -enc except SCCM" works until attackers start using SCCM-looking process names (parent PID spoofing), at which point the exception re-enables the attack. The fix is to invest in detection content versioning with test coverage: treat detection rules like software, with unit tests (Atomic Red Team executions that must fire the rule) and negative tests (legitimate activity samples that must NOT fire). A CI/CD pipeline for detection content — Sigma files in git, automated validation on PR, rollback capability — prevents tuning one rule from silently breaking another. When rules are version-controlled and tested against both attack simulation and production baseline samples before deployment, the whack-a-mole pattern becomes visible as a test failure rather than an operational surprise. SOAR alert clustering (grouping semantically similar alerts from multiple rules into a single investigation case) is a complementary tactical improvement: even if multiple rules fire, the analyst sees one case rather than N alert tickets.