Building Useful Splunk Dashboards for a Home SOC

17 April 2023 | justruss.tech

This covers the actual Splunk configuration needed to build a functional home SOC dashboard from scratch. The assumption is Splunk Enterprise (free trial or licensed) ingesting Windows Security events, Sysmon, and optionally Zeek.

Data ingestion setup

Install the required add-ons before building any searches. Without these, field extractions do not work and all searches run against raw event text:

# Download from Splunkbase:
# - Splunk Add-on for Microsoft Windows (TA-windows)
# - Splunk Add-on for Sysmon (TA-sysmon)

# Install via CLI:
$SPLUNK_HOME/bin/splunk install app TA-windows.tgz -auth admin:password
$SPLUNK_HOME/bin/splunk install app TA-sysmon.tgz -auth admin:password
$SPLUNK_HOME/bin/splunk restart

Configure a Universal Forwarder on each Windows target to send events to Splunk. The inputs.conf on each forwarder:

[WinEventLog://Security]
disabled = false
index = wineventlog

[WinEventLog://Microsoft-Windows-Sysmon/Operational]
disabled = false
renderXml = true
index = sysmon

Verifying field extractions

Before building dashboards, confirm fields are parsing correctly:

index=wineventlog EventCode=4624
| table _time, host, EventCode, Account_Name, Logon_Type, src_ip
| head 10

If Account_Name is empty, the TA-windows add-on is either not installed or not applied to the correct index. Fix with:

# props.conf in TA-windows/default/ should contain:
[WinEventLog:Security]
TRANSFORMS-force_sourcetype = force_wineventlog_security_sourcetype

Dashboard panel 1 — Failed logon attempts

index=wineventlog EventCode=4625 earliest=-24h
| eval Logon_Type_Name=case(
    Logon_Type=="2","Interactive",
    Logon_Type=="3","Network",
    Logon_Type=="10","RemoteInteractive",
    true(),"Other")
| stats count AS Failures, 
        dc(src_ip) AS UniqueSourceIPs,
        values(src_ip) AS SourceIPs
    by Account_Name, Logon_Type_Name, ComputerName
| where Failures > 5
| sort -Failures

Threshold of 5 catches brute force without generating noise from single mistyped passwords.

Dashboard panel 2 — New local admin accounts

index=wineventlog (EventCode=4720 OR EventCode=4728 OR EventCode=4732)
| eval Action=case(
    EventCode==4720, "Account Created",
    EventCode==4728, "Added to Domain Admins",
    EventCode==4732, "Added to Local Admins")
| table _time, host, Action, Account_Name, Subject_Account_Name
| sort -_time

Dashboard panel 3 — Suspicious process parent-child pairs

index=sysmon EventCode=1 earliest=-24h
| eval ParentName=mvindex(split(ParentImage,"\"),-1)
| eval ChildName=mvindex(split(Image,"\"),-1)
| eval Pair=ParentName." > ".ChildName
| stats count by Pair, ComputerName
| where count < 5 AND 
    (ChildName IN ("cmd.exe","powershell.exe","wscript.exe","mshta.exe","cscript.exe")
     OR ParentName IN ("winword.exe","excel.exe","outlook.exe","msaccess.exe"))
| sort count

Office applications spawning cmd.exe or PowerShell is a macro execution indicator. The count < 5 filter prioritises rare combinations — high count pairs are likely legitimate admin activity.

Dashboard panel 4 — PowerShell with encoded commands

index=wineventlog EventCode=4688 earliest=-24h
  (Process_Command_Line="*-EncodedCommand*"
   OR Process_Command_Line="*-enc *"
   OR Process_Command_Line="*-en *")
| rex field=Process_Command_Line "(?i)-e(?:nc|ncodedcommand)?\s+(?P[A-Za-z0-9+/=]{20,})"
| eval decoded=base64decode(b64)
| table _time, host, Account_Name, Process_Command_Line, decoded
| sort -_time

Dashboard panel 5 — New scheduled tasks from unusual locations

index=wineventlog EventCode=4698 earliest=-24h
| rex field=_raw "Task Name:\s+(?P[^\r\n]+)"
| rex field=_raw "Task Content:\s+(?P.+)" 
| rex field=task_xml "Command>(?P[^<]+)</Command"
| where NOT match(command,"(?i)^(C:\\Windows\\|C:\\Program Files)")
| table _time, host, task_name, command, Subject_Account_Name

Alert on high-priority detections

# Convert any of the above searches to an alert:
# Search > Save As > Alert
# Trigger: Scheduled - every 15 minutes
# Condition: Number of results > 0
# Actions: Send email / Webhook to Slack/Teams