CyHelp SPL Queries
SPL Queries

Dashboards & Alerts

Ready-to-paste SPL queries for detection, dashboards, and live alerts.

Curated alert and dashboard queries for Linux clients, Windows clients, and server services. Click any item to expand its SPL query · copy it into Splunk and save as alert or dashboard panel.

HIGH · react immediately MED · check daily LOW · informational DASHBOARD · Panel

Linux Clients · Alerts

ALERT · HIGH Brute-force SSH · many failed logins Trigger: >10 in 5 min

Detects IPs that fail to log in via SSH more than 10 times within 5 minutes.

SPL · Alert Query
index=main sourcetype=linux_secure "Failed password"
| bucket _time span=5m
| stats count by _time, src_ip, user
| where count > 10

Alert type: Scheduled (every 5 min) · Condition: Number of Results > 0

ALERT · HIGH Successful login after multiple failures Credential Stuffing

Same IP has failed attempts first, then a successful login · classic credential stuffing.

SPL
index=main sourcetype=linux_secure
  ("Failed password" OR "Accepted password" OR "Accepted publickey")
| eval outcome=if(match(_raw,"Failed"),"fail","success")
| stats count(eval(outcome="fail")) as fails,
         count(eval(outcome="success")) as success
         by src_ip, user
| where fails > 3 AND success > 0
ALERT · HIGH New sudo user added Privilege Escalation

Detects when a user is added to the sudo group or /etc/sudoers.

SPL
index=main sourcetype=linux_secure
  ("usermod" OR "adduser") "sudo"
| table _time, host, user, _raw
ALERT · MED Login from unknown country / unknown IP First login from this IP

Shows all successful logins from IPs that haven't appeared in the last 30 days.

SPL
index=main sourcetype=linux_secure "Accepted" earliest=-1h
| stats count by src_ip, user, host
| search [search index=main sourcetype=linux_secure "Accepted" earliest=-30d latest=-1h
     | stats count by src_ip
     | eval src_ip=src_ip
     | table src_ip]
    # invert to see only NEW IPs:
| where NOT src_ip IN (known_ips)

Tip: easier to maintain via a Splunk lookup table with known IPs.

ALERT · MED Cron job changed Persistence Mechanism

Changes to /etc/cron* or crontab can be persistence mechanisms.

SPL
index=main sourcetype=syslog
  ("CRON" OR "crontab") ("REPLACE" OR "new" OR "BEGIN EDIT")
| table _time, host, user, _raw
ALERT · LOW New user created useradd / adduser
SPL
index=main sourcetype=linux_secure
  ("new user" OR "useradd" OR "adduser")
| table _time, host, _raw

Linux Clients · Dashboard Panels

DASHBOARD Top login IPs (last 24h) Bar chart
SPL
index=main sourcetype=linux_secure "Accepted" earliest=-24h
| stats count by src_ip
| sort -count
| head 10

Visualization: Bar Chart · X-axis: src_ip · Y-axis: count

DASHBOARD Failed vs. successful logins over time Time series
SPL
index=main sourcetype=linux_secure
  ("Failed password" OR "Accepted password" OR "Accepted publickey")
  earliest=-24h
| eval status=if(match(_raw,"Failed"),"Failed","Success")
| timechart count by status span=1h

Visualization: Line Chart · Split by status

DASHBOARD sudo commands per user Table
SPL
index=main sourcetype=linux_secure "sudo" earliest=-24h
| rex field=_raw "sudo:\s+(?<sudo_user>\w+)\s*:.*COMMAND=(?<cmd>.+)"
| stats count by sudo_user, cmd, host
| sort -count
DASHBOARD Active SSH sessions (Single Value) Number
SPL
index=main sourcetype=linux_secure earliest=-1h
| eval session=if(match(_raw,"session opened"),1,
              if(match(_raw,"session closed"),-1,0))
| stats sum(session) as active_sessions

Visualization: Single Value

Windows Clients · Alerts

Tip Windows Event IDs: 4624 = successful login · 4625 = failed · 4648 = Explicit Credentials · 4720 = user created · 4732 = group changed · 4688 = process started · 7045 = new service
ALERT · HIGH Brute-force Windows login (Event 4625) Trigger: >15 in 5 min
SPL
index=wineventlog EventCode=4625
| bucket _time span=5m
| stats count by _time, src_ip, Account_Name, ComputerName
| where count > 15
ALERT · HIGH New local admin created (Event 4720 + 4732) Privilege Escalation

User created (4720) and added directly to the Administrators group (4732).

SPL
index=wineventlog (EventCode=4720 OR EventCode=4732)
| stats values(EventCode) as events, count by Account_Name, ComputerName
| where mvcount(events) > 1
ALERT · HIGH New service installed (Event 7045) Malware Persistence

An unknown service installed outside of patch windows is suspicious.

SPL
index=wineventlog EventCode=7045
| table _time, ComputerName, ServiceName, ServiceFileName, ServiceType, ServiceStartType
ALERT · HIGH PowerShell encoded command executed (Event 4688) Obfuscation

-EncodedCommand / -enc is a typical attack vector for obfuscated code.

SPL
index=wineventlog EventCode=4688 New_Process_Name="*powershell*" Process_Command_Line="*-enc*"
| table _time, ComputerName, Creator_Process_Name,
         New_Process_Name, Process_Command_Line

Requires: Process Creation Auditing enabled (GPO).

ALERT · MED Login outside business hours (Event 4624) Anomaly

Logins between 22:00 and 06:00 · adjust depending on environment.

SPL
index=wineventlog EventCode=4624 Logon_Type=10
| eval hour=strftime(_time, "%H")
| where hour >= 22 OR hour < 6
| table _time, Account_Name, src_ip, ComputerName, hour

Logon_Type 10 = Remote Interactive (RDP)

ALERT · MED Account locked out (Event 4740) Lockout
SPL
index=wineventlog EventCode=4740
| stats count by Account_Name, Caller_Computer_Name, ComputerName
| sort -count

Windows Clients · Dashboard Panels

DASHBOARD Login successes vs. failures over time Time series
SPL
index=wineventlog (EventCode=4624 OR EventCode=4625) earliest=-24h
| eval status=if(EventCode=4624,"Success","Failure")
| timechart count by status span=1h

Visualization: Line Chart

DASHBOARD Top locked accounts Table
SPL
index=wineventlog EventCode=4740 earliest=-7d
| stats count by Account_Name
| sort -count | head 10
DASHBOARD RDP logins by host Table
SPL
index=wineventlog EventCode=4624 Logon_Type=10 earliest=-24h
| stats count by ComputerName, Account_Name, src_ip
| sort -count
DASHBOARD New processes per host (Top 10) Bar chart
SPL
index=wineventlog EventCode=4688 earliest=-1h
| stats count by New_Process_Name, ComputerName
| sort -count | head 10

Server Services · Alerts

ALERT · HIGH Many HTTP 5xx errors (server error) Trigger: >50 in 5 min

A high server-error rate can indicate an attack or outage.

SPL · Apache / Nginx
index=web (sourcetype=apache_combined OR sourcetype=nginx_access)
  status>=500 earliest=-5m
| stats count by host, status, clientip
| where count > 50
ALERT · HIGH Possible web scan / directory traversal HTTP 404 Flood

An IP producing many 404 errors is probably scanning for endpoints.

SPL
index=web status=404 earliest=-10m
| stats count by clientip, host
| where count > 100
| sort -count
ALERT · HIGH Service/process unexpectedly stopped Systemd / syslog
SPL
index=main sourcetype=syslog
  ("failed" OR "stopped" OR "killed") "systemd"
| rex field=_raw "systemd\[1\]: (?<service>[^:]+).*(?:failed|stopped|killed)"
| stats count by host, service
| sort -count
ALERT · MED MySQL / DB error rate elevated Trigger: >20 in 5 min
SPL
index=db sourcetype=mysql:error earliest=-5m
  ("ERROR" OR "Warning")
| stats count by host
| where count > 20
ALERT · MED No log input from host (silence) Dead sensor detection

If a host has stopped sending logs, it's either down or the forwarder has a problem.

SPL
# Hosts that sent logs in the last hour
index=* earliest=-1h
| stats latest(_time) as last_seen by host
| eval minutes_silent=round((now()-last_seen)/60,1)
| where minutes_silent > 30
| table host, last_seen, minutes_silent
| sort -minutes_silent
ALERT · LOW Large file uploads (HTTP POST > 10MB) Exfiltration indicator
SPL · Nginx / Apache
index=web method=POST earliest=-1h
| eval bytes_mb=round(bytes/1048576,2)
| where bytes_mb > 10
| table _time, clientip, uri, bytes_mb, host
| sort -bytes_mb

Server Services · Dashboard Panels

DASHBOARD HTTP Traffic Overview (Status Codes) Pie / Bar Chart
SPL
index=web earliest=-1h
| eval status_group=case(
    status>=500, "5xx Server Error",
    status>=400, "4xx Client Error",
    status>=300, "3xx Redirect",
    status>=200, "2xx OK",
    1=1, "Other")
| stats count by status_group
| sort -count

Visualization: Pie Chart

DASHBOARD Request rate over time Time series
SPL
index=web earliest=-24h
| timechart count by host span=15m

Visualization: Area Chart

DASHBOARD Top 10 client IPs by requests Bar chart
SPL
index=web earliest=-1h
| stats count by clientip
| sort -count | head 10
DASHBOARD Log volume per host (all sources) Heatmap / Bar
SPL
index=* earliest=-24h
| stats count by host, sourcetype
| sort -count

Visualization: Bar Chart or Statistics Table

DASHBOARD Service health · latest heartbeats Table
SPL
index=* earliest=-15m
| stats latest(_time) as last_seen, count by host
| eval last_seen=strftime(last_seen,"%H:%M:%S")
| eval status=if(now()-strptime(last_seen,"%H:%M:%S")>300,
               " Silent", " Active")
| table host, status, last_seen, count
| sort status

Create an Alert & Dashboard in Splunk

Create an alert

  1. Enter and test the query in Search & Reporting
  2. Save As → Alert
  3. Set title, choose Alert type: Scheduled (e.g. every 5 min)
  4. Under Trigger Conditions: Number of Results > 0
  5. Under Trigger Actions: e.g. email or Slack webhook
  6. Save

Create a dashboard

  1. Run the query → Save As → Dashboard Panel
  2. Create a New Dashboard or add to an existing one
  3. Pick a panel type (Line Chart, Bar Chart, Single Value, Table)
  4. Add more panels via Edit → Add Panel
  5. Adjust the time range filter at the top right of the dashboard
Tip Set dashboards to auto-refresh every 5 minutes: in dashboard edit mode, pick the refresh interval at the top right · keeps everything live during the CTF.