常見的 Web 漏洞 —— 反序列化漏洞

2022-02-03 愛喝酒燙頭的曹操

前段時間因各種原因,終於下定決心好好總結一下反序列化漏洞,耗時兩周,且看且珍惜!

Vulnerability Introduction

反序列化漏洞首次出現在2015年。雖然漏洞較新,但利用十分熱門,主要原因還是太過信任客戶端提交的數據,容易被開發者忽略,該漏洞一般都可執行任意命令或代碼,造成的影響較大。

在身份驗證,文件讀寫,數據傳輸等功能處,未對反序列化接口做訪問控制,未對序列化數據做加密和籤名,加密密鑰使用硬編碼(如Shiro 1.2.4),使用不安全的反序列化框架庫(如Fastjson 1.2.24)或函數的情況下,由於序列化數據可被用戶控制,攻擊者可以精心構造惡意的序列化數據(執行特定代碼或命令的數據)傳遞給應用程式,在應用程式反序列化對象時執行攻擊者構造的惡意代碼,達到攻擊者的目的。

解析認證token、session的位置

將序列化的對象存儲到磁碟文件或存入資料庫後反序列化時的位置,如讀取json文件,xml文件等

將對象序列化後在網絡中傳輸,如傳輸json數據,xml數據等

參數傳遞給程序

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

使用了不安全的框架或基礎類庫,如JMX 、Fastjson和Jackson等

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

在Python和PHP中,一般通過構造一個包含魔術方法(在發生特定事件或場景時被自動調用的函數,通常是構造函數或析構函數)的類,然後在魔術方法中調用命令執行或代碼執行函數,接著實例化這個類的一個對象並將該對象序列化後傳遞給程序,當程序反序列化該對象時觸發魔術方法從而執行命令或代碼。在Java中沒有魔術方法,但是有反射(reflection)機制:在程序的運行狀態中,可以構造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調用任意一個對象的屬性和方法,這種動態獲取程序信息以及動態調用對象的功能稱為Java語言的反射機制。一般利用反射機制來構造一個執行命令的對象或直接調用一個具有命令執行或代碼執行功能的方法實現任意代碼執行。

以pickle模塊為例,假設瀏覽器傳遞序列化後的Cookie給伺服器保存,伺服器經過一些處理後反序列化還原Cookie:


利用pickle模塊和魔術方法__reduce__生成執行命令的Payload:


使用執行whoami命令的Payload替換序列化後的Cookie的值模擬RCE漏洞利用,當正常程序反序列化Cookie值時生成包含__reduce__函數的exec類,從而執行命令:

PHP中通常使用serialize函數進行序列化,使用unserialize函數進行反序列化。

serialize函數輸出格式

輸出的數字基本都是代表長度,在構造Payload時需要注意修改長度。

使用下面代碼創建一個類A並實例化一個對象a,然後輸出序列化對象a後的值:


PHP中序列化後的數據中並沒有像Python一樣包含函數__construct和print的信息,而僅僅是類名和成員變量的信息。因此,在unserialize函數的參數可控的情況下,還需要代碼中包含魔術方法才能利用反序列化漏洞。

使用下面代碼定義一個包含魔術方法__destruct的類A,然後實例化一個對象a並輸出序列化後的數據,在對象銷毀的時候程序會調用system函數執行df命令,然後通過GET方法傳遞參數arg的值給伺服器進行反序列化:


不傳入arg參數時,伺服器返回對象a序列化後的數據和df命令執行的結果,如圖:


利用對象a序列化後的值構造執行id命令的Payload:O"A"{s"test";s"id";},通過arg參數提交之後,在反序列化的過程中成功覆蓋變量test的值為id,並在對象銷毀時執行命令,如圖:


當然,現實環境中幾乎沒有這樣方便的攻擊鏈,需要花不少時間去尋找POP鏈。

PHP反序列化入門之尋找POP鏈(一)

PHP反序列化入門之尋找POP鏈(二)

Java中通常使用Java.io.ObjectOutputStream類中的writeObject方法進行序列化,java.io.ObjectInputStream類中的readObject方法進行反序列化。使用下面代碼將字符串進行序列化和反序列化:


Java序列化數據格式始終以雙字節的十六進位0xAC ED作為開頭,Base64編碼之後為rO0。之後的兩個字節是版本號,通常為0x00 05。


一個Java類的對象要想序列化成功,必須滿足兩個條件:

該類必須實現 java.io.Serializable接口。

該類的所有屬性必須是可序列化的,如果有一個屬性不是可序列化的,則該屬性必須註明是短暫的。


執行程序後生成a.ser文件,以十六進位格式查看文件內容,如圖:


最後5個字節分別為字符串長度和calc的ASCII值。因此,修改文件為下圖所示,即notepad的ASCII值和長度:


現實環境中也沒有這樣方便的攻擊鏈,需要去尋找POP鏈。

從反序列化到命令執行 – Java 中的 POP 執行鏈

FastJson作為史上最快的Json解析庫應用也十分廣泛,在1.2.69版本以下,其AutoType特性在反序列化過程中會導致反序列化漏洞,這個特性就是:在對JSON字符串進行反序列化的時候,會讀取@type參數指定的類,然後把JSON內容反序列化為此類的對象,並且會調用這個類的設置(setter)方法。

實驗環境

前端採用json提交用戶名密碼

後臺使用fastjson 1.2.24版本

源碼和WAR包GitHub地址

創建一個User類,用於查看序列化數據格式,如圖:


創建一個home類用於輸出user對象的序列化數據,如圖:


創建一個login類用於獲取前端頁面提交的json格式用戶名和密碼數據,並使用JSON.parseObject方法進行反序列化解析json數據,在後臺可看到提交的數據,如圖:


訪問home頁面可直接獲取user對象序列化後的結果,如圖:


@type的值為對象所屬的類,user和passwd分別為對象的用戶名屬性和密碼屬性。因此可以利用AutoType特性,構造一個使用@type參數指定一個攻擊類庫,包含類屬性或方法的JSON字符串提交到伺服器,在反序列化時調用這個類的方法達到執行代碼的目的。通常使用java.net.Inet4Address類或java.net.Inet6Address類,通過val參數傳遞域名,利用DnsLog進行漏洞檢測,即:{"@type":"java.net.Inet4Address","val":"DnsLog"}。在登錄頁面輸入用戶名和密碼提交,攔截數據包,修改提交的Json數據,如圖:

雖然伺服器返回錯誤信息,但Payload仍然被成功執行,在DnsLog網站可以看到解析記錄,如圖:

基於JNDI注入

基於ClassLoader

基於TemplatesImpl

由於本實驗僅使用最小依賴編寫,此處不再詳細分析POP鏈。

BinaryFormatter

JavaScriptSerializer

XmlSerializer

DataContractSerializer

。。。

採用Xml提交數據

使用.NET Framework 4.6.1

完整源碼GitHub地址

使用下面代碼定義一個Test類,包含執行ipconfig命令並返回執行結果的函數Run,使用XmlSerializer類將對象序列化後輸出到頁面:


使用下面代碼將提交的XML數據反序列化,並執行對象的Run函數:

對反序列數據加密或籤名,且加密密鑰和籤名密鑰不要使用硬編碼

對反序列化接口添加認證授權

設置反序列化服務僅在本地監聽或者設置相應防火牆策略

禁止使用存在漏洞的第三方框架庫

過濾、禁用危險函數

過濾T3協議或限定可連接的IP

設置Nginx反向代理,實現t3協議和http協議隔離

Java反序列化工具YSoSerial.jar

PHP反序列化工具PHPGGC

.NET反序列化工具YSoSerial.NET

深入理解 JAVA 反序列化漏洞

Java反序列化漏洞從入門到深入

Java反序列化漏洞分析

從反序列化到命令執行 – Java 中的 POP 執行鏈

微信公眾號 |墨守安全

官方網站 |moushou.org.cn

相關焦點

  • PHP反序列化漏洞說明
    序列化可以將對象轉換成字符串,但僅保留對象裡的成員變量,不保留函數方法。PHP序列化的函數為serialize,反序列化的函數為unserialize.舉個慄子:<?反序列化反序列化就是序列化的逆過程,即對於將對象進行序列化後的字符串,還原其成員變量的過程。接上述慄子:<?
  • Java安全之反序列化漏洞分析
    方法,而反序列化是由ObjectInputStream的readObject方法實現的,下圖是作者畫的一個序列化示意圖:何來的漏洞之說?呵呵,意外往往就發生在不經意之間,如果反序列化過程中提供了命令執行的機會,那麼任意命令執行漏洞就產生了,如下我們在Session對象的readObject函數中增加了執行命令的代碼:
  • 文庫 | 反序列化漏洞匯總
    因此,幾乎不可能預料到惡意數據的流動並堵塞(修復)每個潛在的漏洞。簡而言之,反序列化不受信任的輸入是不安全的。漏洞影響不安全的反序列化的影響可能非常嚴重,因為它為大規模增加攻擊面提供了切入點。它允許攻擊者以有害的方式重用現有的應用程式代碼,從而導致許多其他漏洞,通常是遠程執行代碼(RCE)。
  • JAVA反序列化漏洞實例解析
    今天i春秋通過一期《JAVA反序列化學習-基礎篇》公開課,帶大家快速了解預期效果、JAVA編程基礎、漏洞基礎、靶項目搭建四個模塊內容,感興趣的小夥伴速來學習吧!感興趣的小夥伴,識別二維碼立即看課1、漏洞原理我們既然已經知道了序列化與反序列化的過程,那麼如果在反序列化時,這些即將被反序列化的數據是經過特殊構造的呢?如果Java應用對用戶輸入,即不可信數據做了反序列化處理,那麼攻擊者可以通過構造惡意輸入,讓反序列化產生非預期的對象,非預期的對象在產生過程中就有可能帶來任意代碼執行。
  • java反序列化——XMLDecoder反序列化漏洞
    前言最近學習java反序列化學到了weblogic部分,weblogic之前的兩個反序列化漏洞不涉及T3協議之類的,只是涉及到了XMLDecoder
  • 深入剖析 Java 反序列化漏洞
    一、背景在上篇文章中,小編有詳細的介紹了序列化和反序列化的玩法,以及一些常見的坑點。2016 年 Spring RMI 反序列化爆出漏洞,攻擊者可以通過 JtaTransactionManager 這個類,來遠程執行惡意代碼。2017 年 4月15 日,Jackson 框架被發現存在一個反序列化代碼執行漏洞。
  • PHP反序列化漏洞基礎
    一、PHP序列化和反序列化1、PHP反序列化:將變量或者對象轉換成字符串的過程,用於存儲或傳遞PHP的值的過程種,同時不丟失其類型和結構。②在反序列的時候php會根據s所指定的字符長度去讀取後面的字符。如果指定的長度錯誤則反序列化就會失敗。2、session反序列化(1)session概念PHP session時一個特殊的變量,用於存儲有關用戶會話的信息,或更改用戶會話的設置。session變量保存的信息是單一用戶的,並且可供應用程式中的所有界面使用。
  • Yii2 反序列化漏洞復現分析
    1、漏洞描述Yii是一套基於組件、用於開發大型Web應用的高性能PHP框架。Yii2 2.0.38 之前的版本存在反序列化漏洞,程序在調用unserialize() 時,攻擊者可通過構造特定的惡意請求執行任意命令。
  • Java反序列化漏洞從理解到實踐
    利用某個反序列化漏洞。2. 自己手動創建利用載荷。更具體一點,首先我們會利用現有工具來實際操作反序列化漏洞,也會解釋操作的具體含義,其次我們會深入分析載荷相關內容,比如什麼是載荷、如何手動構造載荷等。完成這些步驟後,我們就能充分理解載荷的工作原理,未來碰到類似漏洞時也能掌握漏洞的處理方法。
  • PHP一些常見的漏洞梳理
    以下主要是近期對php一些常見漏洞的梳理,包含php文件包含、php反序列化漏洞以及php偽協議。
  • Web常見漏洞描述及修復建議
    2、減少或不使用代碼或命令執行函數  3、客戶端提交的變量在放入函數前進行檢測  4、減少或不使用危險函數7.任意文件上傳  漏洞描述  文件上傳漏洞通常由於代碼中對文件上傳功能所上傳的文件過濾不嚴或web伺服器相關解析漏洞未修復而造成的,如果文件上傳功能代碼沒有嚴格限制和驗證用戶上傳的文件後綴
  • 乾貨 | PHP反序列化原理及不同類別反序列化漏洞總結
    op"private變量\x00 + 類名 + \x00 + 變量名反序列化漏洞形成條件1、unserialize函數的參數可控2、後臺使用了相應的PHP中的魔法函數反序列化漏洞原理<?PHP語言本身漏洞還有一種PHP語言本身漏洞碰到某種特點情況導致的反序列化漏洞如:__wakeup失效引發(CVE-2016-7124)php版本<5.6.25 | <
  • 看代碼學安全(11) - unserialize反序列化漏洞
    漏洞解析:(上圖代碼第11行正則表達式應改為:』/O:d:/『)題目考察對php反序列化函數的利用。代碼 11行 ,第一個if,截取前兩個字符,判斷反序列化內容是否為對象,如果為對象,返回為空。php可反序列化類型有String,Integer,Boolean,Null,Array,Object。去除掉Object後,考慮採用數組中存儲對象進行繞過。
  • Java 8u20反序列化漏洞分析
    POC解讀8u20是基於7u21的繞過,不熟悉7u21的可以先看這篇文章了解下,看下7u21漏洞的修補方式。漏洞作者找到java.beans.beancontext.BeanContextSupport類對這裡進行了繞過。
  • 技術乾貨 | PHP序列化漏洞原理
    常見的php系列化和反系列化方式主要有:serialize,unserialize;json_encode,json_decode。string serialize ( mixed $value )返回字符串,此字符串包含了表示 value 的字節流,可以存儲於任何地方。
  • 常見WEB基礎漏洞
    '\u0061\u006c\u0065\u0072\u0074\u0028\u0022\u0078\u0073\u0073\u0022\u0029\u003b')">6.url編碼繞過<img src="x"onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%
  • 淺談Python Pickle反序列化
    在目前(我)已知的反序列化漏洞中,有PHP、Python以及Java語言的反序列化漏洞,且漏洞利用的方式多種多樣。這次就先學習一下Python Pickle反序列化漏洞。基礎知識什麼是反序列化序列化說白了就是將對象轉換成字節流,便於保存在內存、文件或者是資料庫中;反序列化則是序列化的逆過程,將字節流還原成對象。
  • PHP反序列漏洞
    CTF常見的魔術方法和觸發條件。__construct 在創建對象時候觸發,一般是用來初始化變量。__destruct 對象被摧毀時調用。__sleep 序列化對象之前就調用此方法。__wakeup 反序列化恢復對象之前調用該方法。__toString 當對象被當做一個字符串輸出時調用。
  • Web安全 | PHP反序列化入門這一篇就夠了
    搞懂反序列化漏洞的前提,先搞懂什麼是序列化:序列化說通俗點就是把一個對象變成可以傳輸的字符串。,但是如果反序列化的內容是用戶可以控制的,且後臺不正當的使用了PHP中的魔法函數,就會導致安全問題有哪些php常見的魔法函數:__construct() 當一個對象創建時被調用__destruct() 當一個對象銷毀前被調用__sleep() 在對象被序列化前被調用__wakeup 將在反序列化之後立即被調用
  • Java序列化對象(JSO):實戰漏洞利用指南
    在本報告中,我們將探討JSO如何受到不安全的反序列化漏洞的影響、網際網路上JSO處理的應用程式的流行程度,以及測試人員如何使用Metasploit框架來驗證涉及JSO的漏洞。1. 與2017年相比,與JSO相關的CVE漏洞在2018年大幅增加。在兩年中,總共確認了近100個漏洞,而2013年至2016年期間僅確認了7個漏洞。2.