/developmentserver/metadatauploader, and in vulnerable builds that endpoint was reachable with no authentication at all. An attacker who could reach it over the network could upload an arbitrary file, including an executable JSP, into a web-reachable directory on the SAP Java application server, then request that file to run code on the host. This is CWE-434 (Unrestricted Upload of File with Dangerous Type), tracked as CVE-2025-31324, scored 10.0 by SAP and 9.8 by NVD, and it has been on CISA's Known Exploited Vulnerabilities catalog since it was disclosed. This is not deserialization and it is not a memory bug. It is a missing gate on an upload endpoint, and it turns an ERP server into an attacker-controlled host.
SAP NetWeaver is the application platform underneath a large share of the world's ERP estates, and the Visual Composer component ships as part of the AS Java stack in the affected VCFRAMEWORK 7.50 line. Visual Composer is a low-code modeling tool that many organizations never actively use, yet it is present and running by default on plenty of NetWeaver installs. That combination, a rarely-used but always-present component exposing an unauthenticated write primitive on a business-critical host, is what makes this one of the more consequential SAP bugs in recent memory. We do not republish weaponized exploit code here. We explain the mechanism, the timeline, and how to determine whether your own perimeter carries the risk. Verifiable security.
The bug in one paragraph
The Metadata Uploader endpoint accepts uploaded content as part of its normal Visual Composer function. In the vulnerable code path, that endpoint did not enforce an authorization check, so a request arriving without any session or credential was still processed and its payload still written to disk. Because the upload accepted arbitrary file types rather than restricting to a safe allow-list, an attacker could send a file the server would happily execute, a JSP being the natural choice on a Java application server. The uploaded file landed in a directory served by the same web container that runs the application, which meant it was directly reachable by URL. At that point the attacker simply requested the file they had just uploaded, the container compiled and executed the JSP, and the attacker had command execution. Two facts stacked on top of each other produce the outcome: no authorization on the write, and no restriction on what could be written. Either one alone is a serious finding. Together they are a pre-authentication path from the open internet to arbitrary code execution.
Be precise about the class, because it is frequently misdescribed. CVE-2025-31324 is an unrestricted file upload, CWE-434. It is not an insecure deserialization bug. SAP later shipped a separate note for CVE-2025-42999, an insecure deserialization issue in the same broad area that was observed in some follow-on exploitation chains, but that is a different weakness with its own identifier, and the details of that second issue should be verified on their own rather than conflated with this one. The upload bug does not need deserialization to reach code execution. The upload itself is the whole exploit.
From one POST to a web shell
The attack is short because the primitive is powerful. An operator sends a single HTTP POST to the uploader endpoint carrying a JSP payload, receives a success response, and then makes an ordinary GET request to the path where the file was written. Publicly reported intrusions have used generic, innocuous-looking filenames for the dropped shell, names like helper.jsp and cache.jsp, precisely so the artifact blends into a busy servlet directory. Once the shell answers, the attacker has an interactive command channel that requires no credentials on every subsequent visit, because the shell itself is the authentication bypass. From there the typical progression is reconnaissance of the SAP host, credential and configuration harvesting, and lateral movement, all running with the privileges of the SAP Java process.
The full chain is two requests: one to write the shell, one to run it. Illustrative, not from any specific host.
Why an ERP RCE is close to worst case
The severity here is not about the elegance of the bug, it is about where it lands. An SAP application server is a trust anchor for the business: it holds financial records, procurement and supply-chain data, HR and payroll information, and it is wired into identity, messaging, and downstream systems across the environment. Code execution on that host is not a foothold on the edge of the network, it is a foothold at the center of the organization's operations. The SAP Java service typically runs under a dedicated operating-system account, commonly the <sid>adm user, which owns the SAP installation and its data directories. Execution as that account means the attacker can read and alter SAP data, plant persistence, extract secrets used to reach connected systems, and pivot, all without ever having presented a credential.
That is why the scoring is what it is. SAP, as the CNA, rates CVE-2025-31324 a CVSS 10.0 with the vector AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H. NVD rates it 9.8. The single difference between the two scores is the Scope metric: SAP scores it Scope Changed (S:C), reflecting that the compromised web-tier component can affect the broader system beyond its own security authority, while NVD scores it Scope Unchanged (S:U), which caps the arithmetic at 9.8. Both agree on the parts that matter operationally: network reachable, low complexity, no privileges required, no user interaction, and full compromise of confidentiality, integrity, and availability. Quote both numbers when you brief this. Presenting only one invites an argument about the wrong thing.
The full exploit is two requests. Neither carries a credential. The second one runs your commands on the ERP server.
Exploited before the patch existed
This was a zero-day. SAP released the fixing Security Note on 2025-04-24, but exploitation had already been observed in the wild before that date. Rapid7 reported activity against the uploader endpoint from at least 2025-03-27, roughly four weeks before a patch was available, which means early victims had no vendor fix to apply while the endpoint was being actively hit. The targeting was not indiscriminate background noise either. Reporting from multiple responders described heavy focus on manufacturing organizations, the kind of operational environments where SAP sits at the core of production and supply-chain planning and where downtime is expensive enough that patching windows are conservative. That is a difficult combination: a pre-auth RCE, exploited before a fix shipped, aimed at a sector that is structurally slow to patch its most critical systems.
The practical lesson from the timeline is that patch status is necessary but not sufficient. An organization that applied the note promptly still needs to assume the window between late March and their patch date was exposed, and to hunt for artifacts left during it. A web shell dropped on 2025-03-30 does not remove itself when you install the April note. Patching closes the door; it does not evict anyone already inside.
How to recognize your exposure
You can assess this without sending a malicious payload, because the exposure is determined by a few readable facts.
- Is the uploader endpoint reachable? Determine whether
/developmentserver/metadatauploaderanswers on any internet-facing or broadly-reachable SAP NetWeaver host. An endpoint that responds pre-authentication is the whole precondition for the attack. - Is Visual Composer present and on an affected build? The component is
VCFRAMEWORK 7.50. Confirm whether it is installed and whether the host predates SAP's 2025-04-24 note, since a public-facing, unpatched instance carries active, catalog-listed risk by definition. - What account does the SAP Java service run as? The blast radius equals the privilege of the process that gets injected. Knowing the run-as account, commonly
<sid>adm, tells you how bad a successful hit is before one happens.
What to do about it
Close CVE-2025-31324 and hunt for prior compromise
- Apply SAP's Security Note for CVE-2025-31324. The note released 2025-04-24 is the fix. Treat any public-facing, unpatched NetWeaver Visual Composer host as an active incident, not a queued ticket.
- If you cannot patch immediately, block access to the endpoint. Restrict or deny reachability to
/developmentserver/metadatauploaderat the reverse proxy or web dispatcher, and constrain the management surface to trusted networks. - Disable Visual Composer if you do not use it. Many estates run the component without ever modeling anything in it. Turning off an unused feature removes the surface entirely.
- Hunt for unexpected JSP files in the servlet path. Look for files that should not be there, including generic names such as
helper.jspandcache.jsp, and review write timestamps against the late-March-onward exposure window. - Review anomalous child processes of the SAP Java service. Shell spawns, network utilities, or archive tools launched by the SAP process are a high-signal indicator that a shell ran under the service account.
- Assume pre-patch exposure and scope for it. Because exploitation ran ahead of the patch, a clean patch state does not prove you were never hit. Check logs and disk for artifacts dated before your remediation.
How Celvex catches this
Find. Prove. Fix. Verify.
A read-only sweep maps internet-facing SAP NetWeaver hosts, checks whether the Metadata Uploader endpoint answers, and fingerprints the Visual Composer build against the known-exploited catalog, without sending a single upload.
A confirmed exposed, catalog-listed surface becomes an Ed25519-signed Proof Capsule carrying the host, the endpoint and version evidence, and the matching CVE-2025-31324 record, reproducible offline by you or your auditor.
The capsule's remediation block names the steps: apply the 2025-04-24 note, block or disable the uploader, reduce the service privilege, and hunt the servlet path for planted JSP files.
A fresh sweep confirms the endpoint is patched, blocked, or no longer exposed. The finding closes and the verified-fix event is recorded for the audit trail.
The reason this bug is so instructive is that it is not clever. There is no exotic gadget chain and no race to win. An endpoint that was meant to authenticate its callers simply did not, and an upload that should have been restricted to safe types was not. The discipline that catches it is the same one that catches its cousins: for every host that accepts input from outside, ask which endpoints answer before login, what they let a stranger write, and what privilege that write inherits. On an ERP server the answer to that question is the whole business, which is exactly why it warrants a faster patch window and a closer watch than almost anything else on the perimeter.
Verifiable security. Find it. Prove it. Fix it. Verify the fix held. That is what we ship.
Sources
- NVD: CVE-2025-31324 (SAP NetWeaver Visual Composer unrestricted file upload)
- Rapid7: Active Exploitation of SAP NetWeaver Visual Composer CVE-2025-31324
- Onapsis: Active Exploitation of SAP Vulnerability CVE-2025-31324
- MITRE CWE-434: Unrestricted Upload of File with Dangerous Type
- CISA Known Exploited Vulnerabilities Catalog
- CELVEX Group: Proof Capsule format
Is your SAP NetWeaver uploader answering strangers?
Free Exposure Check, no signup required. We map your internet-facing SAP NetWeaver hosts, test whether the Metadata Uploader endpoint responds and on which Visual Composer build, and ship a signed Proof Capsule for the highest-confidence finding.
Run a Free Scan →