反序列化攻擊 - 未經授權篡改序列化資料以執行惡意程式碼 - 可能會對組織造成嚴重損害。開發人員和安全團隊必須主動找出關鍵漏洞,揭露攻擊發生的方式、時間和地點。
CVE-2023-34040 就是這種威脅的最新例子,它是 Spring for Apache Kafka 中的反序列化攻擊向量,可導致 RCE (遠端程式碼執行)。事實上,OWASP Top 10 名單強調了反序列化漏洞的普遍性,其中將「不受信任資料的反序列化」列為十大最重要的 Web 應用程式安全風險之一。
OPSWAT MetaDefender Core™等工具及其 SBOM軟體物料清單)引擎對於偵測和預防反序列化攻擊至關重要。這些工具可讓開發人員有效率地掃描及分析其程式碼,確保不會忽略任何弱點。
在這篇文章中,我們的研究員將討論 CVE-2023-34040 的細節及其利用方式,以及如何保護開放原始碼元件的安全,以對抗類似的威脅。
關於 CVE-2023-34040
CVE-2023-34040 揭露了 Spring for Apache Kafka 中的反序列化攻擊向量,當應用不尋常的配置時,可利用此漏洞。此漏洞可讓攻擊者在其中一個反序列化異常記錄標頭中建構惡意序列化物件,導致 RCE。此漏洞影響 Spring for Apache Kafka 2.8.1 至 2.9.10 及 3.0.0 至 3.0.9 版本。
具體而言,應用程式/用戶在下列特定組態和條件下容易受到攻擊:
- ErrorHandlingDeserializer 類別未針對記錄的 key 和/或值進行設定。
- 消費者的 checkDeserExWhenKeyNull 和/或 checkDeserExWhenValueNull 屬性設定為 true。
- 不信任的來源允許發佈到 Kafka 主題。
Apache Kafka
Apache Kafka 由 ApacheSoftware 基金會開發,是一個分散式事件串流平台,設計用來擷取、處理、回應和路由來自資料庫、感測器和mobile 裝置等各種來源的即時資料流。
例如,它可以將通知串流至對客戶活動(如完成產品結帳或付款)作出反應的服務。
在 Apache Kafka 中,事件(也稱為記錄或訊息)是一個資料單元,代表應用程式中每次讀取或寫入資料時發生的事件。每個事件包含一個 key、value、timestamp,以及可選的 metadata 標頭。
鍵-二進位 (可以為空) | 二進位數值 (可以為空) | ||||
壓縮類型 [none, gzip, snappy, lz4, zstd] (無、gzip、snappy、lz4、zstd) | |||||
標題(可選)
| |||||
分割 + 偏移 | |||||
時間戳記 (系統或使用者設定) |
事件被持久地儲存並組織成主題。發送(寫入)事件到 Kafka 主題的用戶端應用程式稱為生產者,而訂閱(讀取和處理)事件的用戶端應用程式稱為消費者。
Spring for Apache Kafka
若要連接 Apache Kafka 與 Spring 生態系統,開發人員可使用 Spring for Apache Kafka,簡化 Java 應用程式中的整合。
Spring for Apache Kafka 提供了強大的工具和 API,簡化了使用 Kafka 傳送和接收事件的流程,使開發人員無需大量複雜的編碼即可完成這些任務。
序列化與反序列化
序列化(Serialization)是將物件的狀態轉換成字串或位元組流的機制。相反,反序列化則是相反的過程,序列化的資料會被轉換回原始的物件或資料結構。序列化允許轉換複雜的資料,使其可以儲存到檔案、透過網路傳送或儲存到資料庫中。序列化和反序列化對於分散式系統中的資料交換是不可或缺的,並可促進軟體應用程式各元件間的溝通。在 Java 中,writeObject() 用於序列化,而 readObject() 用於反序列化。
由於反序列化允許將位元組流或字串轉換為物件,不當處理或缺乏適當的輸入資料驗證會造成重大的安全漏洞,可能導致 RCE 攻擊。
漏洞分析
根據 CVE 描述,OPSWAT 研究員將checkDeserExWhenKeyNull與checkDeserExWhenValueNull設定為 true,以觸發安全漏洞。透過傳送一個 key/value 為空的記錄,並在消費者從生產者接收 Kafka 記錄時進行除錯來進行詳細分析,我們的研究生研究員發現了記錄處理過程中的以下工作流程:
步驟 1:接收記錄(訊息)
接收到記錄後,消費者會呼叫invokeIfHaveRecords()方法,然後再呼叫invokeListener()方法,以觸發已註冊的記錄監聽器(使用@KafkaListener註解註釋的類別)來實際處理記錄。
invokeListener()接著會呼叫invokeOnMessage()方法。
步驟 2:檢查記錄
在invokeOnMessage()方法中,會針對記錄值和組態屬性評估幾個條件,然後決定要執行的下一步。
如果記錄的 key 或值為空,且checkDeserExWhenKeyNull和/或checkDeserExWhenValueNull 屬性明確設定為true,則會呼叫checkDeser()方法檢查該記錄。
步驟 3:從標頭檢查異常
在checkDesr() 中,消費者會不斷地呼叫getExceptionFromHeader()來擷取記錄元資料中的任何異常(如果有的話),並將結果儲存在稱為exception 的變數中。
步驟 4:從標頭擷取例外資訊
getExceptionFromHeader()方法是用來從 Kafka 記錄的標頭中抽取並傳回異常。它首先擷取記錄的標頭,然後獲得標頭的值,該值儲存在一個位元組陣列中。
之後,它會將標頭值的位元組陣列轉寄給byteArrayToDeserializationException()方法作進一步處理。
步驟 5:反序列化資料
在byteArrayToDeserializationException() 中,resolveClass( ) 函數會被覆寫,以限制只對允許的類別進行反序列化。此方法可防止任何未明確允許的類的反序列化。標頭的位元組數組值只有在符合resolveClass() 中設定的條件時,才能在byteArrayToDeserializationException () 中進行反序列化,而 resolveClass() 只允許DeserializationException類別進行反序列化。
然而,DeserializationException類擴展了標準Exception類,並包含一個有四個參數的構建器。最後一個參數cause 代表觸發DeserializationException 的原始異常,例如IOException或ClassNotFoundException。
Throwable類是 Java 中所有可被當作異常或錯誤丟出的物件的超類。在 Java 程式語言中,Throwable、Exception 和Error等異常處理類可以安全地進行反序列化。當異常被反序列化時,Java 允許Throwable父類別被載入和實體化,其檢查要求比一般類別低。
根據工作流程和綜合分析,如果序列化的資料對應到繼承自父類別Throwable 的惡意類別,就有可能繞過條件檢查。這樣就可以反序列化惡意物件,執行有害程式碼,並可能導致 RCE 攻擊。
開發
如分析所示,利用此漏洞需要產生惡意資料,透過 Kafka 標頭記錄傳送給消費者。一開始,攻擊者必須建立一個擴充Throwable類的惡意類,然後利用小工具鏈來達到遠端執行程式碼的目的。小工具是應用程式中可供攻擊的程式碼片段,藉由將它們串連在一起,攻擊者可以達到觸發有害動作的「sink 小工具」。
以下是一個惡意的類別,可以利用 Spring for Apache Kafka 的這個漏洞:
接下來,會建立惡意類的實體,並將其作為參數傳給DeserializationException類建構器中的 cause 參數。然後 DeserializationException 範例會序列化成一組位元組流,隨後被用來作為惡意 Kafka 記錄標頭的值。
如果攻擊者成功欺騙受害者使用他們的惡意生產者,他們就能控制傳送到消費者的 Kafka 記錄,創造入侵系統的機會。
當有漏洞的消費者從惡意生產者接收到包含空鍵和值的 Kafka 記錄,以及記錄標頭中的惡意序列化實例時,消費者就會處理該記錄,包括反序列化過程。這最終會導致遠端執行程式碼,讓攻擊者入侵系統。
在MetaDefender Core中使用 SBOM 減緩 CVE-2023-34040
為了有效降低與 CVE-2023-34040 相關的風險,組織需要一套全面的解決方案,以提供對其開放原始碼元件的能見度與控制。
MetaDefender Core 的基礎技術 SBOM 提供了強大的解決方案。SBOM 是所有使用中的軟體元件、程式庫和相依性的全面清單,可讓組織主動、有效率地追蹤、保護和更新他們的開放原始碼元件。
有了 SBOM,安全團隊可以
- 快速找出易受攻擊的元件:立即識別受反序列化攻擊影響的開放原始碼元件。這可確保迅速採取行動,修補或取代易受攻擊的函式庫。
- 確保主動修補與更新:透過 SBOM 持續監控開放原始碼元件,以掌握反序列化漏洞。SBOM 可偵測過時或不安全的元件,以便及時更新並降低遭受攻擊的風險。
- 保持合規性和報告:SBOM 可協助組織符合法規要求,因為法規框架越來越強制軟體供應鏈的透明度。
結束語
反序列化漏洞是一個重大的安全威脅,可用於攻擊各種應用程式。這些漏洞會在應用程式反序列化惡意資料時發生,讓攻擊者執行任意程式碼或存取敏感資訊。Spring for Apache Kafka 中的 CVE-2023-34040 漏洞就嚴厲地提醒我們反序列化攻擊的危險性。
為了防止反序列化攻擊,必須實施先進的工具,例如OPSWAT MetaDefender Core 及其 SBOM 技術。組織可以深入瞭解其軟體供應鏈,確保及時修補漏洞,並保護自己免受不斷演變的威脅。主動保護開放原始碼元件不僅是最佳做法,也是保護現代系統免於潛在攻擊的必要條件。