Skip to main content

Command Palette

Search for a command to run...

Lab 23: Writing My First Splunk Detection Rule

Updated
4 min readView as Markdown
Lab 23: Writing My First Splunk Detection Rule
R
Self-taught cybersecurity practitioner documenting the path from zero to root. SOC analyst, CTF player, detection engineer. 29 hands-on labs and counting.

Lab 22 got Splunk running.

180 events indexed. 76 SSH brute force events confirmed in the index. The pipeline was alive.

But a SIEM with no detection rules is still just a search engine. Lab 23 is where Splunk learns to recognize an attack.


The SPL Query

Splunk's search language is called SPL — Search Processing Language. If you've worked in Elastic's KQL, the concepts transfer immediately. The syntax is different. The logic is identical.

The query I wrote targets two patterns in /var/log/auth.log that indicate SSH brute force activity:

source="/var/log/auth.log" "Failed password" OR "Invalid user" | stats count by host

Breaking it down:

  • source="/var/log/auth.log" — scopes the search to the authentication log

  • "Failed password" OR "Invalid user" — matches the two event types generated by failed SSH authentication attempts

  • | stats count by host — aggregates the results, showing how many failures occurred per host

Clean. Readable. Effective. The same logic as the KQL rule from Lab 12 in Elastic — different syntax, same detection intent.


Configuring the Alert

Writing the query is step one. Turning it into a live detection rule is step two.

Splunk's alert configuration lives under Save As → Alert from the search interface. Here's how the rule was configured:

Setting Value
Title SSH Brute Force Detection
Alert Type Real-time
Trigger Condition Per-Result
Action Add to Triggered Alerts
Severity Medium
Status Enabled

A few of these settings matter more than they look:

Real-time means Splunk evaluates the query continuously against new incoming events — not on a schedule. The moment a matching event hits the index, the rule runs.

Per-Result means one alert fires per matching event. For SSH brute force detection, this is the right choice — you want visibility into every individual failure, not just a summary. It gives analysts the granularity to spot patterns and track attack progression.

Add to Triggered Alerts means the alert shows up in Splunk's Triggered Alerts dashboard where analysts can review, investigate, and act on it.


Validation

A rule that's never been tested against real data is a rule you can't trust. Lab 13 taught me that lesson.

Before saving the alert, I ran the SPL query against existing log data to confirm it was matching the right events.

Result: 75 events matched.

All 75 were SSH brute force events from Labs 13 and 21 — the same failed authentication attempts I'd been tracking through the entire Elastic series. Every event was from the kali host, sourced from /var/log/auth.log, exactly as expected.

The rule was validated. Then saved. Then confirmed enabled in the Splunk Alerts list.


What This Lab Actually Taught Me

Building the same detection rule in two different SIEMs back to back makes something obvious that's easy to miss when you're only working in one platform:

The logic is the platform-agnostic part.

The decision to target "Failed password" and "Invalid user" events, aggregate by host, and trigger per result — that's detection engineering thinking. That's the skill. KQL and SPL are just the syntax it gets expressed in.

An analyst who understands why the rule is designed the way it is can reproduce it in any SIEM they sit down in front of. An analyst who memorized the steps in one tool is starting from zero every time the platform changes.

That's the difference this lab series is designed to make.


What's Next

The rule is live. The alert is enabled. 75 historical events are already matched.

Lab 24 is the real test — a live attack simulation to confirm the alert fires end-to-end on fresh brute force activity. Not historical data. Not a validation run. A real attack, in real time, against a live detection rule.

That's the post coming next.

Full lab report on GitHub: github.com/RouteToRoot


Follow the journey:
GitHub: github.com/RouteToRoot
YouTube: youtube.com/@RouteToRoot_Sec
Portfolio: routetoroot.io