flawopen.com/安全でないデシリアライズ/TypeNameHandling
Newtonsoft.Json TypeNameHandling:信頼できない JSON の安全な設定
通常の 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 と明示的な分岐を使います。
よくある質問
それだけでは安全ではありません。Auto はデシリアライズ中に $type を読む場合があります。TypeNameHandling.None または審査済み型だけを許可する厳格な binder を使います。
はい。識別子と派生型をコードで宣言する明示方式で、.NET 7 以降なら [JsonDerivedType] が使えます。型集合はアプリコードが制限します。
全ソリューションで TypeNameHandling、SerializationBinder、JsonConvert.DeserializeObject を検索します。ASP.NET 起動処理と共有設定を調べ、外部 JSON の経路を追跡し、None 以外の各経路に厳格な binder があることを確認します。