Generic Splunk queries from documentation and vendor blogs tend to fail the same way in real environments — they're written without knowing your field schema, your log sources, or what "normal" looks like for your user population. The queries below are built from production SOC environments and include the tuning notes that make the difference between a query that runs and a query that actually works.
These queries target index=win_* with Windows Security Event Log as the primary source (EventCode=4688 for process creation). Field names follow mixed PascalCase/snake_case as common in enterprise Splunk deployments. Adjust index names and field aliases for your environment.
1. Suspicious Process Creation (4688)
Process creation with command line logging is your highest-value data source for endpoint detection. The query below focuses on the parent-child relationships that matter most — scripting engines spawned from unexpected parents, compilers running outside dev machines, and processes with suspicious command line content.
index=win_* (sourcetype="WinEventLog:Security" OR source="XmlWinEventLog:Security") EventCode=4688 earliest=-24h latest=now | eval parent=lower(coalesce(Parent_Process_Name, ParentProcessName, parent_process)) | eval image=lower(coalesce(New_Process_Name, ProcessName, process_name)) | eval cmdline=coalesce(Process_Command_Line, CommandLine, process) /* Suspicious parents */ | where match(parent, "(winword|excel|outlook|powerpnt|onenote| chrome|msedge|firefox|iexplore|mshta| rundll32|wscript|cscript)\.exe$") /* Suspicious children */ | where match(image, "(powershell|pwsh|cmd|wscript|cscript| mshta|certutil|bitsadmin|regsvr32| csc|vbc|cvtres)\.exe$") /* Exclude known-good management tools */ | where NOT match(parent, "(taniumclient|ccmexec|msbuild| devenv|onexagentui)\.exe$") | eval suspicion=case( match(cmdline, "(?i)(http|https|\\\\)"), "HIGH", match(cmdline, "(?i)Users\\\\.*Downloads"), "HIGH", match(cmdline, "(?i)-enc|-encodedcommand"), "HIGH", 1==1, "MEDIUM") | table _time host user parent image cmdline suspicion | sort 0 -_time
The benign parent allowlist (taniumclient, ccmexec, msbuild) is a starting point — your environment will have additional management agents. Add them with ticket references, not just the process name.
2. Credential Access — Brute Force Detection
index=win_* sourcetype="WinEventLog:Security" EventCode=4625 earliest=-1h latest=now | eval account=lower(coalesce(Target_Account_Name, TargetUserName, user)) | eval src_ip=coalesce(Source_Network_Address, IpAddress, src_ip) | stats count as FailedLogins dc(src_ip) as SourceIPs values(src_ip) as IPList values(Failure_Reason) as FailureReasons by account host | where FailedLogins >= 20 | eval SprayIndicator=if(SourceIPs > 5, "POSSIBLE_SPRAY", "BRUTE_FORCE") | sort - FailedLogins
3. Lateral Movement — Pass the Hash / PtT
index=win_* sourcetype="WinEventLog:Security" EventCode=4624 Logon_Type=3 Authentication_Package=NTLM earliest=-24h latest=now | eval src=coalesce(Source_Network_Address, IpAddress, src_ip) | eval account=lower(coalesce(Target_Account_Name, TargetUserName)) /* Exclude machine accounts */ | where NOT match(account, "\$$") /* Exclude localhost */ | where src != "127.0.0.1" AND src != "::1" AND src != "-" | stats count as AuthCount dc(host) as TargetHosts values(host) as TargetHostList by account src | where TargetHosts >= 3 | sort - TargetHosts
4. Data Exfiltration — Large Volume Transfers
index=network* earliest=-1h latest=now | eval bytes_out_mb=round(bytes_out/1048576, 2) | where bytes_out_mb > 100 /* Exclude known backup/cloud sync destinations */ | where NOT match(dest_ip, "(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)") | lookup geoip dest_ip OUTPUT Country as dest_country | stats sum(bytes_out_mb) as TotalMB dc(dest_ip) as UniqueDestinations values(dest_country) as Countries by src_ip user | sort - TotalMB
5. Persistence — Scheduled Task Creation
index=win_* sourcetype="WinEventLog:Security" EventCode=4698 earliest=-24h latest=now | rex field=Task_Content "<Command>(?P<task_command>[^<]+)</Command>" | rex field=Task_Content "<Arguments>(?P<task_args>[^<]+)</Arguments>" | eval suspicious=case( match(task_command, "(?i)(powershell|cmd|wscript|mshta|regsvr32)"), "SUSPICIOUS_BINARY", match(task_args, "(?i)(http|https|-enc|-encodedcommand)"), "SUSPICIOUS_ARGS", match(task_command, "(?i)Users\\\\.*Temp"), "SUSPICIOUS_PATH", 1==1, "REVIEW") | where suspicious != "REVIEW" | table _time host user Task_Name task_command task_args suspicious | sort 0 -_time
When a scheduled task fires this alert, immediately pull 4624/4625 events for the same account in the 30 minutes before task creation. Attackers who create persistence tasks almost always authenticate to the host first — that authentication event is often your best pivot for tracing the access path back.
The Intelligence Pack rotates across CrowdStrike, Sentinel, and Splunk. Every Splunk issue includes SPL with your exact environment assumptions baked in — index names, field aliases, benign parent allowlists, and the tuning notes that make it work in a real environment rather than a lab.
Join — $14.99/mo SOC Starter Kit — $39