FlawOpen

flawopen.com/Javaデシリアライズ/ObjectInputStreamの安全性

ObjectInputStreamは信頼できないデータにも安全ですか?

Javaセキュリティリファレンス
かんたんに説明

通常は安全ではありません。readObject()はJavaオブジェクトを復元し、クラス定義のメソッドを実行する場合があります。添付物に独自の初期化手順まで実行させるフォームのようなものです。悪意あるストリームは既存クラスの挙動に届く可能性があります。コード実行の有無はクラス、ライブラリ、経路、入力境界によります。

危険:ネイティブなオブジェクト復元
// 攻撃者が制御するバイト列をここに渡さない。
try (var in = new ObjectInputStream(untrustedStream)) {
    Object value = in.readObject();
    handle(value);
}
より安全:固定データ型を解析
// 信頼できない入力では広範な多態型指定を無効にする。
ObjectMapper mapper = new ObjectMapper();
OrderRequest value = mapper.readValue(
    untrustedBytes, OrderRequest.class
);
validate(value);

欠陥が到達可能になる経路

API、キュー、キャッシュ、ファイル取込がユーザー制御のバイト列を受け取ります。ObjectInputStream.readObject()に届くと、JVMはプロセス内のシリアライズ可能クラスからオブジェクトを復元します。ガジェットチェーンはその挙動をたどる一つの経路で、全ストリームに特別なペイロードがあるわけではありません。OracleはCVE-2015-4852で、対象WebLogic版へのT3経由の未認証攻撃を記録しました。すべての利用がリモート到達可能という意味ではありません。

ネイティブシリアライズを除去できない場合

よくある質問

ObjectInputFilterでreadObject()は安全になりますか?

狭い許可リストと読込前の制限でリスクは下がりますが、万能なサニタイザーではありません。許可クラスと動作、フィルターの有効化、アプリ側検証と認可が重要です。可能ならユーザー制御データにネイティブ形式を使わないでください。

一次資料

関連項目 安全でないデシリアライズ:リスクと対策 | flawopen.com Newtonsoft.Json TypeNameHandling:安全な設定方法 PHP unserialize() と信頼できない入力 Python pickle.load():信頼できないデータのリスク Ruby YAML.load は安全?Psych のバージョンと safe_load .NET BinaryFormatter:リスクと移行