1. 程式人生 > 其它 >反序列化漏洞的利用

反序列化漏洞的利用

目錄

PHP序列化格式

假設一個物件User具有以下屬性:

$user->name = "carlos";
$user->isLoggedIn = true;

序列化之後,物件可能如下所示:

O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;}

解釋如下:

  • O:4:"User"——表示具有四個字元的類名物件User
  • 2 ——表示物件具有兩個屬性
  • s:4:"name"——表示第一個屬性的變數名是4個字元的字串name
  • s:6:"carlos"——表示第一個屬性的值為6個位元組的字串carlos
  • s:10:"isLoggedIn"——表示第二個屬性的Key值是10個字元的字串isLoggedIn
  • b:1——第二個屬性的值是布林型別的true

PHP序列化的基本方法是serialize()和unserialize()。如果有程式碼訪問許可權,應該首先找查unserialize()程式碼中的任何一處並進行分析

JAVA序列化格式

某些語言(例如 Java)使用二進位制序列化格式。這更難閱讀,但如果您知道如何識別一些明顯的標誌,您仍然可以識別序列化資料。例如,序列化的 Java 物件總是以相同的位元組開始,這些位元組像ac ed 以十六進位制編碼、像rO0 以Base64進行編碼。

操作序列化物件

利用一些反序列化漏洞就像更改序列化物件中的屬性一樣簡單。由於物件狀態被持久化,您可以研究序列化資料以識別和編輯感興趣的屬性值。然後,您可以通過其反序列化過程將惡意物件傳遞到網站中。這是基本反序列化利用的第一步。

從廣義上講,在操作序列化物件時可以採用兩種方法:

  • 可以直接以位元組流的形式編輯物件
  • 可以用相應的語言編寫一個簡短的指令碼來自己建立和序列化新物件。

在使用二進位制序列化格式時,後一種方法通常更容易。

修改物件屬性

假設一個網站:
它使用一個序列化的User物件在 cookie 中儲存有關使用者會話的資料。
如果攻擊者在 HTTP 請求中發現了這個序列化物件,他們可能會對其進行解碼以找到以下位元組流:

O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;}

該isAdmin屬性是一個明顯的興趣點。
攻擊者可以簡單地將屬性的布林值更改為1(true),重新編碼物件,並用這個修改後的值覆蓋他們當前的 cookie。
單獨看序列化字串,這好像沒什麼用。但是,假設網站使用此 cookie 來檢查當前使用者是否有權訪問某些管理功能:

$user = unserialize($_COOKIE);
if ($user->isAdmin === true) {
// allow access to admin interface
}

這個易受攻擊的程式碼將User根據來自 cookie 的資料例項化一個物件,包括攻擊者修改的isAdmin屬性。任何時候都不會檢查序列化物件的真實性。然後將此資料傳遞到條件語句中,在這種情況下,將允許輕鬆提升許可權。

這種簡單的場景在實際環境中並不常見。但是,以這種方式編輯屬性值是訪問不安全反序列化暴露的大量攻擊面的第一步。

修改資料型別

在PHP中,(==)運算子屬於一個弱型別的比較,只比較值而不比較型別
類似於 6=="6"這種返回的是true,PHP自動將字串轉換為數字型別

更加有趣的是,這樣也適用於任何以數字開頭的字串,PHP只會將初始有效數字轉換為整數值進行比較,而後面的字串完全忽略,比如 5=="5 adddfeasfs" 返回的是true
甚至: 0 == "aaaadfafsaf" 返回的是true ,因為沒有數字在這裡,PHP將整個字串設定為整數0.

這種鬆散的不叫會帶來反序列化的危險:
比如以下程式碼:

$login = unserialize($_COOKIE)
if ($login['password'] == $password) {
// log in successfully
}

只要儲存的密碼不以數字開頭,條件就會始終返回true,從而啟用身份驗證繞過。請注意,這是唯一可能的,因為反序列化保留了資料型別。如果程式碼直接從請求中獲取密碼,則0將轉換為字串,條件將評估為false。
請注意,在修改任何序列化物件格式的資料型別時,記住更新序列化資料中的任何型別標籤和長度指示器也很重要。否則,序列化的物件將被破壞並且不會被反序列化。

直接使用二進位制格式時,我們建議使用 BApp 商店提供的 Hackvertor 擴充套件。使用 Hackvertor,您可以將序列化資料修改為字串,它會自動更新二進位制資料,相應地調整偏移量。這可以為您節省大量的手動工作。

0=="sdsdsfaf" true
0=="123sdsdsfaf" false
1=="sdsdsfaf" false
1=="1sdsdsfaf" true
1=="a 1 sdsdsfaf" false

使用應用程式功能

除了簡單地檢查屬性值外,網站的功能還可能對來自反序列化物件的資料執行危險的操作。在這種情況下,您可以使用不安全的反序列化來傳遞意外資料並利用相關功能進行破壞。

例如,作為網站“刪除使用者”功能的一部分,通過訪問$user->image_location屬性中的檔案路徑來刪除使用者的個人資料圖片。如果這$user是從序列化物件建立的,攻擊者可以通過將修改後的物件與image_location設定為任意檔案路徑來利用它。刪除他們自己的使用者帳戶也會刪除這個任意檔案。

魔術方法

魔術方法是各種語言中面向物件程式設計的共同特徵。它們有時通過在方法名稱前加上雙下劃線或將其括起來來表示。

開發者可以在類中新增魔術方法,以便預先確定在相應的事件或場景發生時應該執行哪些程式碼。呼叫魔術方法的確切時間和原因因方法而異。PHP 中最常見的例子之一是__construct(),每當類的物件被例項化時就會呼叫它,類似於 Python 的__init__. 通常,像這樣的建構函式魔術方法包含初始化例項屬性的程式碼。但是,開發人員可以自定義魔術方法來執行他們想要的任何程式碼。

魔術方法被廣泛使用,本身並不代表漏洞。但是,當它們執行的程式碼處理攻擊者可控制的資料時,例如來自反序列化物件的資料,它們就會變得危險。攻擊者可以利用這一點在滿足相應條件時自動呼叫反序列化資料的方法。

最重要的是,在這種情況下,某些語言具有在反序列化過程中自動呼叫的魔術方法。

例如,PHP 的unserialize()方法查詢並呼叫物件的__wakeup()魔術方法。

在 Java 反序列化中,同樣適用於readObject()方法,它本質上就像一個用於“重新初始化”序列化物件的建構函式。該ObjectInputStream.readObject()方法用於從初始位元組流中讀取資料。但是,可序列化的類也可以宣告自己的readObject()方法,如下所示:

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {...};

這允許類更緊密地控制其自身欄位的反序列化。至關重要的是,以readObject()這種方式宣告的方法充當在反序列化期間呼叫的魔術方法。

您應該密切注意包含這些型別的魔術方法的任何類。它們允許您在物件完全反序列化之前將資料從序列化物件傳遞到網站程式碼中。這是建立更高階漏洞利用的起點。

注入任意物件

正如我們所見,有時可以通過簡單地編輯網站提供的物件來利用不安全的反序列化。然而,注入任意物件型別可以開闢更多的可能性。

在面向物件的程式設計中,物件可用的方法由它的類決定。因此,如果攻擊者可以操縱作為序列化資料傳入的物件類,他們就可以影響在反序列化之後甚至反序列化期間執行的程式碼。

反序列化方法通常不會檢查它們正在反序列化的內容。這意味著您可以傳入網站可用的任何可序列化類的物件,並且該物件將被反序列化。這有效地允許攻擊者建立任意類的例項。該物件不屬於預期類別這一事實無關緊要。意外的物件型別可能會導致應用程式邏輯異常,但此時惡意物件已經被例項化。

如果攻擊者可以訪問原始碼,他們可以詳細研究所有可用的類。為了構建一個簡單的漏洞利用,他們會尋找包含反序列化魔術方法的類,然後檢查它們中是否有任何人對可控資料執行危險操作。然後攻擊者可以傳入此類的序列化物件以使用其魔術方法進行攻擊。

包含這些反序列化魔法方法的類也可用於發起更復雜的攻擊,涉及一長串方法呼叫,稱為“小工具鏈”。

小工具鏈

“小工具”是應用程式中存在的一段程式碼,可以幫助攻擊者實現特定目標。單個小工具可能不會直接對使用者輸入進行任何有害操作。然而,攻擊者的目標可能只是呼叫一個方法,將他們的輸入傳遞給另一個小工具。通過以這種方式將多個小工具連結在一起,攻擊者可能會將他們的輸入傳遞到一個危險的“接收器小工具”中,從而造成最大的損害。

重要的是要了解,與其他一些型別的漏洞利用不同,小工具鏈不是攻擊者構建的鏈式方法的有效載荷。所有程式碼已經存在於網站上。攻擊者唯一控制的是傳遞到小工具鏈的資料。這通常使用在反序列化期間呼叫的魔術方法來完成,有時稱為“啟動小工具”。

在外界,許多不安全的反序列化漏洞只能通過使用小工具鏈來利用。這有時可能是一個簡單的一兩步鏈,但構建高嚴重性攻擊可能需要更復雜的物件例項化和方法呼叫序列。因此,能夠構建小工具鏈是成功利用不安全反序列化的關鍵方面之一。

使用預先構建的小工具鏈

手動識別小工具鏈可能是一個相當艱鉅的過程,如果沒有原始碼訪問許可權幾乎是不可能的。幸運的是,您可以先嚐試一些使用預先構建的小工具鏈的選項。

有多種工具可以提供一系列已在其他網站上成功利用的預先發現的鏈。即使您無法訪問原始碼,您也可以使用這些工具以相對較少的工作量來識別和利用不安全的反序列化漏洞。由於包含可利用的小工具鏈的庫的廣泛使用,這種方法成為可能。例如,如果 Java 的 Apache Commons Collections 庫中的小工具鏈可以在一個網站上被利用,那麼實現該庫的任何其他網站也可以使用相同的鏈來利用。

ysoserial

一種用於 Java 反序列化的工具是“ysoserial”。這使您可以為您認為目標應用程式正在使用的庫選擇提供的小工具鏈之一,然後傳入您要執行的命令。然後,它根據選定的鏈建立適當的序列化物件。這仍然涉及一定數量的反覆試驗,但與手動構建自己的小工具鏈相比,它的勞動密集度要低得多。

請注意,並非 ysoserial 中的所有小工具鏈都允許您執行任意程式碼。相反,它們可能用於其他目的。例如,您可以使用以下方法來幫助您在幾乎任何伺服器上快速檢測不安全的反序列化:

  • 該URLDNS鏈會觸發對提供的 URL 的 DNS 查詢。最重要的是,它不依賴於使用特定易受攻擊的庫的目標應用程式,並且可以在任何已知的 Java 版本中執行。這使其成為用於檢測目的的最通用的小工具鏈。如果您在流量中發現序列化物件,您可以嘗試使用此小工具鏈生成一個物件,該物件觸發與 Burp Collaborator 伺服器的 DNS 互動。如果是這樣,您可以確定在您的目標上發生了反序列化。
  • JRMPClient是另一個可用於初始檢測的通用鏈。它會導致伺服器嘗試與提供的 IP 地址建立 TCP 連線。請注意,您需要提供原始 IP 地址而不是主機名。該鏈在所有出站流量都受到防火牆保護的環境中可能很有用,包括 DNS 查詢。您可以嘗試使用兩個不同的 IP 地址生成有效負載:一個本地地址和一個受防火牆保護的外部地址。如果應用程式立即響應具有本地地址的負載,但掛起具有外部地址的負載,導致響應延遲,這表明 gadget 鏈有效,因為伺服器嘗試連線到防火牆地址。在這種情況下,響應中細微的時間差異可以幫助您檢測伺服器上是否發生反序列化,即使是在盲目的情況下。

PHP 通用小工具鏈

大多數經常遭受不安全反序列化漏洞影響的語言都有等效的概念驗證工具。例如,對於基於 PHP 的站點,您可以使用“PHP 通用小工具鏈”(PHPGGC)。

需要注意的是,該漏洞是使用者可控資料的反序列化,而不僅僅是網站程式碼或其任何庫中存在的小工具鏈。小工具鏈只是一種在注入有害資料後操縱其流動的手段。這也適用於依賴於不受信任資料的反序列化的各種記憶體損壞漏洞。換句話說,即使網站確實以某種方式設法插入了所有可能的小工具鏈,它也可能仍然容易受到攻擊。

使用記錄的小工具鏈

總是值得在網上檢視是否有任何記錄的漏洞可以用來攻擊目標網站。即使沒有用於自動生成序列化物件的專用工具,您仍然可以找到流行框架的文件小工具鏈並手動調整它們。

建立自己的漏洞利用

當現成的小工具鏈和記錄的漏洞利用不成功時,您將需要建立自己的漏洞利用。

要成功構建您自己的小工具鏈,您幾乎肯定需要訪問原始碼。第一步是研究此原始碼以識別包含在反序列化期間呼叫的魔術方法的類。評估這個魔法方法執行的程式碼,看看它是否直接對使用者可控的屬性做了任何危險的事情。這總是值得檢查以防萬一。

如果魔術方法本身無法利用,它可以作為小工具鏈的“啟動小工具”。研究啟動小工具呼叫的任何方法。這些是否會對您控制的資料造成危險?如果沒有,請仔細檢視它們隨後呼叫的每個方法,依此類推。

重複此過程,跟蹤您可以訪問哪些值,直到您到達死衚衕或識別您的可控資料被傳遞到的危險接收器小工具。

一旦您確定瞭如何在應用程式程式碼中成功構建小工具鏈,下一步就是建立一個包含您的負載的序列化物件。這只是研究原始碼中的類宣告並使用漏洞利用所需的適當值建立有效序列化物件的一個​​案例。正如我們在之前的實驗中所見,這在處理基於字串的序列化格式時相對簡單。

使用二進位制格式,例如在構建 Java 反序列化漏洞時,可能特別麻煩。對現有物件進行細微更改時,您可能會習慣於直接使用位元組。但是,當進行更重要的更改時,例如傳入一個全新的物件,這很快就變得不切實際。為了自己生成和序列化資料,用目標語言編寫自己的程式碼通常要簡單得多。

在建立您自己的小工具鏈時,尋找機會使用這個額外的攻擊面來觸發二級漏洞。

本文來自部落格園,作者:{Zeker62},轉載請註明原文連結:https://www.cnblogs.com/Zeker62/p/15175718.html