flawopen.com/安全でないデシリアライズ/.NET BinaryFormatterの安全性
.NETのBinaryFormatterは安全ですか?
MicrosoftはBinaryFormatterを安全ではなく、安全化できないと説明しています。入力を信頼できると思っていても、使用をやめるよう推奨しています。.NET 9ではAPI型は残りますが、組み込み実装は常にPlatformNotSupportedExceptionをスローします。旧ランタイムやサポート対象外の互換パッケージには元のリスクが残ります。
// 信頼境界を越えるデータをデシリアライズしない。 using System.IO; using System.Runtime.Serialization.Formatters.Binary; public static class LegacyReader { public static object Deserialize(Stream input) => new BinaryFormatter().Deserialize(input); } // 次の制限のないポリモーフィック形式も削除する: SoapFormatter NetDataContractSerializer LosFormatter ObjectStateFormatter // ASP.NET ViewStateの内部で使用 // SerializationBinderでも安全にはならない。
// データ形式はアプリケーションコードで宣言する。 // Nullable reference types make the DTO contract explicit. #nullable enable using System; using System.IO; using System.Text.Json; public sealed record MyDto(int Id, string Name); public static class DtoReader { public static MyDto Parse(ReadOnlySpan<byte> json) { // 入力サイズを制限し、アプリ規則を検証する。 if (json.Length > 65_536) throw new InvalidDataException(); MyDto? value = JsonSerializer.Deserialize<MyDto>(json); if (value is null || value.Id <= 0 || string.IsNullOrWhiteSpace(value.Name) || value.Name.Length > 100) throw new InvalidDataException(); return value; } } // 古いNRBFファイルはNrbfDecoderで調査する // レコードを確認し、許可値だけをDTOへ移す。 // 任意のランタイム型を再生成しない。
BinaryFormatterが危険な理由
BinaryFormatter.Deserializeはストリームからオブジェクトグラフを再構築し、攻撃者が制御するデータに実行フローを左右させる可能性があります。Microsoftはサービス拒否、情報漏えい、リモートコード実行のリスクを警告しています。根本原因は制限のないポリモーフィックなデシリアライズです。シリアライズデータが処理される型やオブジェクト状態に影響できます。設定スイッチで未信頼バイトを安全に解析するAPIにはできません。
リスクは公開HTTPエンドポイントだけではありません。ファイル、キャッシュ、キュー、DBレコード、デスクトップクライアントのメッセージ、クラウド同期状態も後で攻撃者の影響を受ける可能性があります。バイトがシステムに入り移動する経路を追跡し、「自分たちが書いた」「内部データ」というラベルを恒久的な信頼の根拠にしないでください。
SerializationBinderだけでは不十分
独自のSerializationBinderは解決対象の型を制限できますが、Microsoftはbinderなどの設定ではサービス拒否を軽減できず、他の攻撃にも不十分な場合があると明記しています。binderは移行の代わりになりません。削除までの間も未信頼入力を受け入れないでください。
既存コードの利用箇所を探す
ソース、プロジェクト参照、ランタイム設定でBinaryFormatter、IFormatter、SoapFormatter、NetDataContractSerializer、LosFormatter、ObjectStateFormatterを検索します。セッションプロバイダー、キャッシュアダプター、キュー処理、ファイル入出力、旧ASP.NET Web Formsを確認します。ViewStateは通常MACで保護されています。保護を有効にし、machine keyを守ってください。そのMACも一般的なBinaryFormatterデシリアライズを安全にはしません。
形式とランタイムに応じて移行する
新しいデータには、互換性と形式に応じてSystem.Text.Json、DataContractSerializer、MessagePack、protobuf-netなど明示的な契約を選びます。直接置き換えられる製品はありません。古いNRBFファイルを保持する場合、.NET 9のNrbfDecoderは記録を読み取っても符号化された型をインスタンス化しません。構造を検証し、期待する値だけをDTOへ移します。WinForms/WPFのリソース、クリップボード、ドラッグ&ドロップは別途移行ガイドを確認してください。
よくある質問
Microsoftは、データが信頼できると思われる場合も移行を推奨しています。ストレージ、キャッシュ、ファイル、同期、下流サービスは信頼境界を越えることがあります。各データ源の書き込み可能な主体を調べ、前提に頼らずBinaryFormatterを廃止してください。
.NET 9ではAPI型は残りますが、組み込み実装は以前の互換スイッチに関係なく常にPlatformNotSupportedExceptionをスローします。更新前に利用箇所を調査して移行してください。サポート対象外の互換パッケージは脆弱な実装を復元するため、対策にはなりません。
Json.NETの既定値はTypeNameHandling.Noneで、payloadの型メタデータから任意のCLR型を選びません。未信頼入力に対してNone以外を有効にしないでください。ポリモーフィズムが必要ならアプリ側の厳格なallowlistを使い、ライブラリの指針に従います。TypeNameHandlingは安全?も参照。
参考資料
- Microsoft Learn — BinaryFormatter security guide
- Microsoft Learn — BinaryFormatter migration guide
- Microsoft Learn — Choose a BinaryFormatter replacement
- Microsoft Learn — Safely read NRBF payloads with NrbfDecoder
- Microsoft Learn — SYSLIB0011
- Microsoft Learn — ASP.NET ViewState MAC
- CWE-502 — Deserialization of Untrusted Data
- Is Json.NET TypeNameHandling safe?