FlawOpen

flawopen.com/安全でないデシリアライズ/TypeNameHandling

Newtonsoft.Json TypeNameHandling:信頼できない JSON の安全な設定

CWE-502: Deserialization of Untrusted Dataリファレンス
要点

通常の JSON はデータを表し、.NET 型はコードが選択します。TypeNameHandling を有効にすると $type が型解決に影響する場合があります。信頼できない入力では None にします。多態性が必要なら厳格な ISerializationBinder で検証するか、コードで宣言した限定的な識別子マッピングを使います。

脆弱な設定
var settings = new JsonSerializerSettings {
    // Any non-None mode needs a strict binder
    TypeNameHandling = TypeNameHandling.Auto,
    // No binder: input $type can resolve CLR types
};

var value = JsonConvert.DeserializeObject<Base>(
    untrustedJson, settings);
修正済み
// Safest default for untrusted JSON
var settings = new JsonSerializerSettings {
    TypeNameHandling = TypeNameHandling.None,
};

// For polymorphism, dispatch over a closed set:
var token = JObject.Parse(json);
Base value = token["kind"]?.ToString() switch {
    "circle" => token.ToObject<Circle>(),
    "square" => token.ToObject<Square>(),
    _ => throw new JsonException("Unknown kind"),
};

// System.Text.Json also supports opt-in derived
// types through [JsonDerivedType] (.NET 7+).

開発者が TypeNameHandling を有効にする理由

よくある理由は多態データです。Shape のコレクションを Circle や Square として保持する必要があります。Json.NET は $type で型名を読み書きします。信頼できない入力ではメタデータが実行時型に影響し、リスクは許可型とデシリアライズ動作によって異なります。危険な連鎖には副作用を持つ到達可能な型が必要で、JSON だけでは成立しません。

信頼境界は逆向きに設計します。コードが検証済み識別子の限定集合から派生型を選びます。System.Text.Json は [JsonDerivedType] などで明示的な多態性をサポートしますが、JSON の任意の CLR 名は有効化しません。関連境界は BinaryFormatter ガイドを参照してください。

カスタム ISerializationBinder で十分ですか?

外部データで TypeNameHandling が None 以外なら、厳格な ISerializationBinder が必要です。アプリ所有の正確な型名を少数だけ許可し、他は拒否します。許可型、converter、constructor、setter、callback を確認してください。binder は解決を制限しますが任意型を無害にはしません。可能なら None と明示的な分岐を使います。

よくある質問

TypeNameHandling.Auto は信頼できない JSON に安全ですか?

それだけでは安全ではありません。Auto はデシリアライズ中に $type を読む場合があります。TypeNameHandling.None または審査済み型だけを許可する厳格な binder を使います。

System.Text.Json は安全な多態性をサポートしますか?

はい。識別子と派生型をコードで宣言する明示方式で、.NET 7 以降なら [JsonDerivedType] が使えます。型集合はアプリコードが制限します。

.NET アプリをどう監査しますか?

全ソリューションで TypeNameHandling、SerializationBinder、JsonConvert.DeserializeObject を検索します。ASP.NET 起動処理と共有設定を調べ、外部 JSON の経路を追跡し、None 以外の各経路に厳格な binder があることを確認します。

参考資料

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