FlawOpen
● CWE-502 / Unsafe Deserialization

安全でないデシリアライズ:リスクと対策

信頼できない pickle、Java Serialization、PHP unserialize のデータが危険な動作を起こす仕組みと、置き換え・制限方法を解説します。

💡 やさしい説明 (ELI5)

シリアライズは模型の組み立て説明書を郵送するようなものです。デシリアライズは説明に従ってデータを再構成します。形式によっては再構成中にクラスを指定したり hook を呼んだりします。信頼できない説明を受け入れると、想定外の動作を起こす可能性があります。影響は形式、runtime、利用可能なクラス、アプリの状況によって異なります。

Core Concepts & Key Terms

シリアライズ / デシリアライズ
データやオブジェクトを保存・転送用の表現に変換し、プログラム内で解析または再構成すること。
デシリアライズ hook
Python __reduce__、Java readObject、PHP __wakeup / __unserialize など、オブジェクト再構成時に動く可能性がある callback。
Gadget chain
既存ライブラリの動作をつなぎ、想定外の効果を起こす連鎖。利用可能性はアプリとライブラリのバージョンに依存します。
デシリアライズフィルター
オブジェクトストリーム読込時にクラスやグラフ指標を制限する方針です。リスクを下げますが、信頼できない native object stream の利用を推奨するものではありません。

How Unsafe Deserialization Can Become an Exploit Chain

Step 1

信頼できないバイト列がデコーダーに届く

Cookie、API body、queue message、保存レコードなどに攻撃者が影響できるデータが含まれます。

Step 2

アプリが native object format を呼び出す

コードが Python pickle、Java ObjectInputStream、PHP unserialize() などにバイト列を渡します。

Step 3

再構成中に形式固有の動作が起きる

形式や到達可能なクラスに応じて、constructor、hook、autoload、ライブラリメソッドがアプリの検証より前に実行されることがあります。

Step 4

影響は到達可能な動作次第

利用可能な gadget や hook が不正な影響を起こすことがありますが、入力が単に失敗したりリソースを消費したりする場合もあります。常にコード実行になるわけではありません。

Python / Flask: Unsafe Object Loading vs. Primitive JSON Validation

脆弱なパターン
# VULNERABLE: pickle can execute behavior during unpickling.
from flask import Flask, request
import pickle

app = Flask(__name__)

@app.post("/api/session")
def load_session():
    # Never deserialize attacker-controlled bytes with pickle.
    session = pickle.loads(request.get_data())
    return {"user_id": session.user_id}
安全性を高めた検証
# SAFER: parse JSON primitives, then validate expected shape.
from flask import Flask, abort, request

app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 16 * 1024

@app.post("/api/session")
def load_session():
    payload = request.get_json()
    if not isinstance(payload, dict):
        abort(400, "Expected a JSON object")

    user_id = payload.get("user_id")
    if type(user_id) is not int or user_id <= 0:
        abort(400, "Invalid user_id")

    # Resolve authorization and session state server-side.
    return {"user_id": user_id}

エンジニアリング向け強化チェックリスト

JSON にも入力サイズの上限と構造検証が必要です。従来型のオブジェクト形式では、クラスの許可リストだけに頼らず、デシリアライズ前にシリアライズ済みバイト列そのものを認証し、鍵を保護してください。MAC はデータを暗号化せず、リプレイも防ぎません。

← セキュリティディレクトリを見る 脆弱性ガイドを見る →