Back to projects

Home lab · detection + automation

AI-Assisted SOC Automation Lab

October to December 2025 4 min read

Cut my own triage time from 45 to 8 minutes across 10 self-run attacks

Splunkn8nLLM (GPT-4.1 mini)MCP serverDFIR IRISSysmonMITRE ATT&CKVirusTotalAbuseIPDBSlack

I built this by following MyDFIR’s SOC Automation 2.0, including its advanced sections for VirusTotal enrichment, DFIR IRIS ticketing, and the MCP server that lets the AI query the SIEM. The extensions are mine: I attacked the Windows host from Kali, wrote additional detection rules from what I saw, and tuned the SSH brute-force rule down from firing on a single failed login.

10
Detection rules
each mapped to MITRE ATT&CK
45 → 8 min
My triage time
self-run attacks, lab
10
Attacks self-run
Metasploit / Meterpreter / Hydra
5
VMs orchestrated
Win10, Splunk, n8n, Kali, DFIR IRIS

Why I built it

I wanted to understand alert triage from the inside: not just read a SIEM alert, but see the whole path from a raw endpoint event to an analyst-ready summary in Slack, and feel where the time actually goes. Building it end to end was the only way to learn which parts of triage are mechanical enough to automate and which still need a person.

What I built

  • Stood up the stack across five VMs and chose Sysmon with the SwiftOnSecurity config on the Windows 10 endpoint on purpose: default Windows logging misses what detection needs, so Sysmon gives me full process creation with command lines and hashes, registry writes, and network connections. The Universal Forwarder ships that to a Splunk SIEM server, and the remaining VMs run n8n, a DFIR IRIS case-management instance, and a Kali attack box.
  • Wrote the detection logic in Splunk SPL and mapped each rule to MITRE ATT&CK by the behavior it catches, not just a label. The SSH brute-force rule is the one I tuned hardest: a single failed sign-in is meaningless, so I aggregate failures by source over a time window and only alert past a threshold. Others key off specific telemetry, like registry Run-key persistence firing on Sysmon EventCode 13 writes to the autostart paths.
  • Built the n8n workflow that catches each Splunk alert on a webhook and hands it to an LLM (GPT-4.1 mini via the OpenAI API) running a tier-1 analyst prompt that summarizes the alert, enriches the indicators, assesses severity against MITRE ATT&CK, and recommends next actions, then posts a clean writeup to Slack.
  • Wired the AI to real tools rather than just text: it calls AbuseIPDB and VirusTotal itself, and a confirmed alert opens a DFIR IRIS ticket instead of only pinging a channel. The VirusTotal results are genuinely mine, since the file hashes come from my own Sysmon telemetry for the Meterpreter and Atomic Red Team payloads I detonated. The source IPs from my Kali box are private, so AbuseIPDB has nothing on them; I demonstrated that enrichment path with a known-bad public IP instead.
  • Connected the AI to an MCP server so it can query Splunk directly in natural language instead of only reacting to a forwarded alert. I can ask what happened on a host or in a time window and it builds and runs the SPL itself, then summarizes what it found and what to do next.
  • Validated detections by generating the activity myself from Kali, using Hydra for brute force plus Metasploit, Meterpreter, and Atomic Red Team for the endpoint rules, then confirming each one fired on the telemetry it was meant to catch.

MITRE ATT&CK coverage

T1003.001 · LSASS credential dumpingT1055 · Process injectionT1059.001 · PowerShellT1078 · Valid accounts (successful brute force)T1110 · Brute forceT1547.001 · Registry Run-key persistenceT1543.003 · Service installation

Sample detection rule

One of the ten rules: registry Run-key persistence via Sysmon (EventCode 13, T1547.001)

index=dfir-project source="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=13
(TargetObject="*\\CurrentVersion\\Run*" OR TargetObject="*\\CurrentVersion\\RunOnce*"
 OR TargetObject="*\\Winlogon\\*" OR TargetObject="*\\userinit*")
| table _time, Computer, Image, TargetObject, Details, EventType

In a real SOC

In a real SOC the value here is not the AI, it is the discipline around it. An alert is only useful once its false positives are tuned down, which is the SSH brute-force lesson, and that same loop fights alert fatigue on a live queue. The risk I think hardest about is the one the AI introduces: it reads attacker-influenced log data, so prompt injection is a real concern, and anything that lets a model reach the SIEM should stay read-only, able to investigate but never change data. I keep a human in the loop for the same reason, because the model will state things the telemetry does not support. Running against a hosted model also keeps this lab-only on privacy grounds; a production version would use a local LLM.

Screenshots

A walk through the build in screenshots. Click any to view it full size.

Fig 1n8n workflow: webhook → LLM → AbuseIPDB / VirusTotal → Slack
Fig 2The 10 detection rules in Splunk
Fig 3The tier-1 analyst prompt driving the model
Fig 4Enriched alert in Slack (enrichment validated with a substituted known-bad public IP)
Fig 5Registry-persistence detection (Sysmon EventCode 13)
Fig 6Meterpreter alert summarized to Slack

What I learned

  • The SSH brute-force rule taught me the most. Firing on one failed login is noise, so the real work was finding the threshold and time window that catch an actual brute force while leaving normal mistyped logins alone.
  • Wiring the AI to an MCP server changed what it could do. Instead of only summarizing an alert it was handed, it can go ask Splunk its own questions, which is much closer to real investigation than canned enrichment.
  • The AI is genuinely useful for the mechanical parts of triage, but it will confidently narrate things the data does not support, so a human stays in the loop and the pipeline ends at a person, not an automated action. Feeding alerts to a hosted model is also a privacy risk, which is why this stays a lab and a production version would use a local LLM.
  • The 45-to-8-minute figure is my own timing on my own self-run attacks in this lab. It measures how much of my manual triage the pipeline removed, not a production MTTD.