
Self-contained security training lab reproducing CVE-2026-20253 (Splunk Enterprise unauthenticated RCE). Provides a Docker-based environment to practice web exploitation, privilege escalation, and credential theft through a documented attack chain.
Splunk Enterprise 10.2.3 · PostgreSQL recovery sidecar · CWE-306 (Missing Authentication for Critical Function) An authorized, self-contained reproduction that models the real advisory for defensive education. It does not ship Splunk's proprietary code.
This repository is a Vulhub/DVWA-style security-training lab. It stands up a
faithful model of Splunk Enterprise 10.2.3 and reproduces the documented
behavior behind CVE-2026-20253: the bundled PostgreSQL recovery sidecar
exposes privileged file-write and SQL-execution functions with no real
authentication (a blank/any Basic header is accepted), and the Splunk web
tier relays __raw/v1/postgres/* to that sidecar before the login gate.
Chained, this yields unauthenticated remote code execution as the
non-root splunk service account.
The lab is fully solvable end to end: fingerprint the edge, follow a pre-auth health badge to the internal recovery API, prove arbitrary file write, steal the internal Postgres credential, and pivot a SQL-restore file-write primitive into code execution on a scheduled modular-input script.
| Vendor advisory | SVD-2026-0603 |
| CVE | CVE-2026-20253 |
| Weakness | CWE-306 — Missing Authentication for Critical Function |
| Affected | Splunk Enterprise 10.2.3 |
| Fixed in | Splunk Enterprise 10.2.4 |
| CVSS 3.1 | 9.8 (Critical) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
edge network core network
┌───────────────────┐ ┌───────────────────────────────┐
browser ─▶ proxy :8080 ──▶ web :8001 (SPA)
(nginx edge) └▶ splunkd :8089 ─┬─▶ db :5432 (postgres)
login API + ├─▶ redis :6379 (jobs/cache)
__raw relay ───┼─▶ pg-sidecar :5435 ◀── THE VULN
│ (recovery API, blank Basic)
forwarders ─▶ ingest :8088 (HEC) ─────────┘
scheduler ──▶ runs modular-input script
as `splunk` (uid 1000) — RCE sink
shared volume app_data mounted into
pg-sidecar (write) + scheduler (exec)
Two Docker bridges: edge (proxy) and core (everything else). In the
vulnerable build the pg-sidecar sits on core and is reachable from the web
tier's relay — that reachability is the point. The patched overlay isolates it.
cp .env.example .env
docker compose up --build -d
Then browse to http://localhost:8080.
The critical exploit (the recovery sidecar) is fully unauthenticated — you do not need to log in to reach it. The seeded platform accounts below exist only as grey-box vantage points for discovery (reading Splunk's own audit logs in Search & Reporting). Hand participants the analyst account and let them discover the rest.
These credentials are intentionally documented — this is a self-contained training lab, not a production system. The exercise does not require cracking or escalating any of them; the critical
pg-sidecarrecovery API is unauthenticated. Full operator notes live indocs/DEPLOYMENT.md.
There are two flags to capture. Both are SPLUNK{...} strings; their values
live in the lab and are revealed in the docs — they are intentionally not
printed here so you can earn them.
__raw relay, get past the sham Basic auth, and leak the
internal Postgres credential from the sidecar's .pgpass.splunk. Turn the sidecar's file-write
and SQL-restore primitives into code execution on the scheduled
modular-input script, then read the protected secret.Do not skip ahead: docs/DISCOVERY_WALKTHROUGH.md
is written to be discovered, not spoiled. A graduated hint ladder and the full
instructor solution exist for training staff but are kept out of this package
so the exercise stays a blind solve.
The patched/ tree mirrors Splunk's real fix (10.2.4) plus the advisory's
workaround, layered as defense in depth: real credential validation on the
recovery routes, backupFile path-traversal sanitization, elimination of the
libpq connection-string injection, a non-superuser restore role, dropping the
pre-auth __raw relay, and network isolation of the sidecar. See
patched/PATCH_NOTES.md.
Bring up the hardened build with the overlay:
docker compose -f docker-compose.yml -f patched/deploy/compose.override.hardened.yml up --build -d
Mirroring the advisory's mitigation, you can disable the recovery sidecar
entirely without patching — the analog of setting [postgres] disabled = true
in server.conf. Set the following in your .env and recreate the stack:
PG_SIDECAR_DISABLED=true
With the sidecar disabled, the recovery/* functions are gone and the chain is
broken at the source.
Training material. This lab is an authorized, self-contained reproduction that models Splunk Enterprise CVE-2026-20253 for defensive education. It does not contain Splunk's proprietary source or binaries; the services here are an independent re-implementation of the documented vulnerable behavior. Use only against this lab. Running these techniques against systems you do not own is illegal.
| Service | Image | Listens | Published | Role |
|---|
proxy | splunk/proxy:10.2.3 | 8080 | 8080:8080 | nginx edge; Splunk Web + __raw relay entrypoint |
web | splunk/web:10.2.3 | 8001 | — | Splunk Web single-page app (static) |
splunkd | splunk/splunkd:10.2.3 | 8089 | — | Splunk daemon / web tier: login API + the pre-session /{locale}/splunkd/__raw/v1/postgres/* relay |
ingest | splunk/ingest:10.2.3 | 8088 | 8088:8088 | HTTP Event Collector (token auth) |
pg-sidecar | splunk/pg-sidecar:10.2.3 | 5435 | — | THE VULNERABILITY — PostgreSQL recovery sidecar (/v1/postgres/*) |
scheduler | splunk/scheduler:10.2.3 | — | — | runs the scheduled modular-input script as splunk → RCE sink |
db | postgres:16-alpine | 5432 | — | internal Postgres the sidecar backs up / restores |
redis | redis:7-alpine | 6379 | — | job queue / cache |
| Username | Password | Role | Notes |
|---|
admin | Str@ta-Admin-2026! | admin | Full platform admin (Settings, Users, Data Inputs) |
j.okafor | Analyst!Winter24 | analyst | Start here — read-only Search & Reporting console |
m.reyes | Operator#2311 | operator | Manages sources / cluster views |
svc_forwarder | fwd-3f9a1c77b204 | operator | Service account (HEC forwarder) |
| Doc | Audience / purpose |
|---|
docs/DISCOVERY_WALKTHROUGH.md | Discovery-driven path from fingerprint to RCE |
docs/ROOT_CAUSE.md | Why it's vulnerable (CWE-306) and how the patch fixes it |
docs/ARCHITECTURE.md | Services, networks, the __raw relay, and data flow |
docs/DETECTION.md | Blue-team detection opportunities and signatures |
docs/PLAYER_GUIDE.md | Participant briefing and scope |
docs/HINTS.md | Graduated hint ladder — kept internal, not included in this package |
docs/INSTRUCTOR_GUIDE.md | Training staff only — full solution + flags, kept internal, not included |
docs/DEPLOYMENT.md | Stand up, operate, and tear down the environment |