SAP NetWeaver Visual Composer Unrestricted File Upload RCE (CVE-2025-31324)
by aristois913 (repo attributes original exploitation to "ShinyHunters" / "Scattered LAPSUS$ Hunters") · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-31324
- Category
- web
- Affected product
- SAP NetWeaver Application Server (AS) Java — Visual Composer component (VCFRAMEWORK), specifically the Metadata Uploader servlet
- Affected versions
- SAP NetWeaver AS Java instances with the Visual Composer Development Server component (VCFRAMEWORK) installed and exposed; per source repository (includes a version-7.5-specific code path)
- Disclosed
- 2026-07-06
- Patch status
- patched
Tags
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | aristois913 (repo attributes original exploitation to “ShinyHunters” / “Scattered LAPSUS$ Hunters”) |
| CVE / Advisory | CVE-2025-31324 |
| Category | web |
| Severity | Critical |
| CVSS Score | 10.0 (per NVD) |
| Status | Weaponized |
| Tags | sap-netweaver, visual-composer, metadatauploader, unrestricted-file-upload, java-deserialization, jsp-webshell, rce, cwe-434, cwe-502, python |
| Related | CVE-2025-42999 |
Affected Target
| Field | Value |
|---|---|
| Software / System | SAP NetWeaver Application Server (AS) Java — Visual Composer component (VCFRAMEWORK), specifically the Metadata Uploader servlet |
| Versions Affected | SAP NetWeaver AS Java instances with the Visual Composer Development Server component (VCFRAMEWORK) installed and exposed; per source repository (includes a version-7.5-specific code path) |
| Language / Platform | Python 3 (attacker-side exploit), targeting a Java EE application server (SAP NetWeaver AS Java) |
| Authentication Required | No |
| Network Access Required | Yes |
Summary
CVE-2025-31324 is an unrestricted file upload vulnerability in the Metadata Uploader servlet of SAP NetWeaver Visual Composer (VCFRAMEWORK), which is exposed unauthenticated on the /developmentserver/metadatauploader endpoint. The root cause is that this endpoint accepts attacker-supplied ZIP archives containing a .properties file and deserializes/parses their content without verifying the caller’s identity or the destination path, allowing an attacker to write arbitrary files — including JSP web shells — directly into the server’s deployed web root. The PoC in this repository (main.py) crafts a raw Java serialized object stream (a java.util.Properties/SDO gadget chain terminating in either direct Runtime.exec() or an XSLTC/TemplatesImpl-style gadget) inside the zipped .properties payload, POSTs it to the metadata uploader, and can either execute an arbitrary OS command directly or drop a persistent JSP web shell at a predictable path under /irj/. Successful exploitation yields remote code execution with the privileges of the SAP service user (typically sidadm), i.e. full compromise of the SAP application server.
Vulnerability Details
Root Cause
The Visual Composer Metadata Uploader servlet accepts unauthenticated POST requests containing a ZIP file (with CONTENTTYPE=MODEL&CLIENT=1 query parameters) whose contents are processed server-side without any authentication check or content/path validation. The PoC builds the ZIP payload like this:
| |
The newContent written into the .properties entry is not a plain properties file — it is a hand-assembled raw Java serialization stream (java.util.Properties / SAP SDO object graph) that the server deserializes with an unfiltered ObjectInputStream-style path. For arbitrary command execution, the payload embeds an XSLTC TemplatesImpl-based gadget chain (ysoserial-style bytecode blobs, h1/h2/tail) whose static initializer calls Runtime.getRuntime().exec(...) with the attacker-supplied command. For the web-shell-drop path, the payload instead targets a java.io.FileOutputStream/sun.misc.BASE64Decoder gadget chain that writes an attacker-controlled Base64-decoded byte array to a path constructed as:
../apps/sap.com/irj/servlet_jsp/irj/root/<random8chars>.jsp
i.e. directly into the deployed irj web application’s document root, using a ..-relative path traversal from the storage location the uploader normally writes model files to. Because the endpoint performs no authentication and no restriction on the destination path or file extension, this results in unauthenticated arbitrary file write, and because the written file is a .jsp inside a servlet container’s web root, it results directly in RCE (cmd= request parameter passed to Runtime.exec).
Attack Vector
- Attacker sends an unauthenticated HTTP POST to
TARGET/developmentserver/metadatauploader?CONTENTTYPE=MODEL&CLIENT=1with a ZIP body containing a single.propertiesentry. - That entry is not a real properties file but a raw Java serialized object stream built from SAP SDO/Properties gadget classes, optionally followed by an XSLTC
TemplatesImplgadget chain (for--command) or aFileOutputStream/Base64Decoder gadget chain (for--dropshell). - The server deserializes the stream server-side (via the Visual Composer Metadata Uploader’s model-import logic) without an object input filter, triggering the embedded gadget chain during deserialization.
- In
--commandmode, the gadget chain directly invokesRuntime.getRuntime().exec(cmd), executing an arbitrary OS command with the privileges of the SAP service user (response containingCause - Getter getOutputPropertiesindicates a version match / likely success; the PoC also auto-retries with an alternateserialVersionUIDbyte pattern for AS Java 7.5). - In
--dropshellmode, the gadget chain instead writes a Base64-decoded JSP web shell to../apps/sap.com/irj/servlet_jsp/irj/root/<random>.jsp, which is then reachable atTARGET/irj/<random>.jsp?cmd=<os-command>for repeatable command execution without re-sending the exploit.
Impact
Unauthenticated, remote arbitrary command execution and/or a persistent unauthenticated web shell on the SAP NetWeaver AS Java host, with privileges of the SAP service user (sidadm), leading to full compromise of the SAP system (and, per the repo’s notes, chained in the wild in 2025 with CVE-2025-42999 by threat actors tracked as ShinyHunters/Scattered Spider).
Environment / Lab Setup
Target: SAP NetWeaver Application Server (AS) Java with Visual Composer (VCFRAMEWORK) /
Development Server component installed and network-reachable
(endpoint: /developmentserver/metadatauploader), e.g. SAP NW AS Java 7.5x lab instance
Attacker: Python 3 with `requests` installed (pip install requests)
Network: Direct HTTP(S) reachability to the target's NetWeaver AS Java HTTP port (commonly 50000)
Proof of Concept
PoC Script
See
main.pyin this folder.
| |
Detection & Indicators of Compromise
POST /developmentserver/metadatauploader?CONTENTTYPE=MODEL&CLIENT=1 HTTP/1.1
Content-Type: application/octet-stream
Unexpected .jsp files under .../irj/servlet_jsp/irj/root/ with short random
alphabetic names (e.g. abcxwyqz.jsp) not part of a legitimate deployment
Signs of compromise:
- Unauthenticated POST requests to
/developmentserver/metadatauploaderwithCONTENTTYPE=MODEL&CLIENT=1, especially with binary/ZIP bodies containing a bare.propertiesentry - Newly created, randomly-named
.jspfiles under theirjweb root (servlet_jsp/irj/root/) not tied to any deployment/change record - Child processes spawned by the SAP NetWeaver Java process (
sidadm) shortly after such requests, or requests to/irj/<random>.jsp?cmd=... ClassNotFoundException/deserialization error noise in NetWeaver logs correlated with metadata uploader requests
Remediation
| Action | Detail |
|---|---|
| Primary fix | Apply SAP Security Note 3594142 (and related follow-up notes) which patches the Visual Composer Metadata Uploader to require authentication and validate/restrict deserialization and file-write behavior; upgrade to the SAP-recommended patched kernel/support package level |
| Interim mitigation | If Visual Composer is not in active use, disable the VCFRAMEWORK / Development Server service entirely; restrict network access to /developmentserver/metadatauploader at the reverse proxy/firewall to trusted management networks only; monitor for and remove unexpected .jsp files under the irj web root |
References
Notes
Mirrored from https://github.com/aristois913/CVE-2025-31324 on 2026-07-06. The repository’s main.py self-identifies its exploit chain (via comments and print strings) as originating from the “ShinyHunters”/“Scattered LAPSUS$ Hunters” collectives; the raw serialized gadget-chain byte blobs embedded in the script are unmodified from that source and are opaque (base64-encoded Java class bytecode), so they are mirrored as-is without further decompilation in this note.
| |