flawopen.com/Désérialisation non sécurisée/TypeNameHandling
Newtonsoft.Json TypeNameHandling : configuration sûre pour le JSON non fiable ?
Le JSON décrit les données ; votre code choisit le type .NET. Avec TypeNameHandling, $type peut influencer la résolution de type pendant la désérialisation. Gardez None pour les entrées non fiables. Si le polymorphisme est nécessaire, validez les types avec un ISerializationBinder strict ou utilisez une correspondance fermée de discriminateurs déclarée dans le code.
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+).
Pourquoi les développeurs activent TypeNameHandling
Les données polymorphes en sont la raison habituelle : une collection Shape peut devoir être restaurée comme Circle ou Square. Json.NET lit et écrit les noms de type via $type. Avec une entrée non fiable, ces métadonnées peuvent influencer le type résolu ; le risque dépend des types autorisés et de leur comportement à la désérialisation. Une chaîne dangereuse exige un type accessible ayant des effets de bord ; le JSON seul ne suffit pas.
La frontière de confiance doit fonctionner à l’inverse : le code choisit un sous-type parmi un ensemble fermé de discriminateurs validés. System.Text.Json propose le polymorphisme opt-in par des attributs comme [JsonDerivedType] ; il n’active pas de noms CLR arbitraires du JSON. Consultez les conseils sur BinaryFormatter pour une frontière connexe.
Un ISerializationBinder personnalisé suffit-il ?
Un ISerializationBinder strict est la défense requise par Json.NET lorsque TypeNameHandling diffère de None pour les données externes. Associez seulement quelques noms exacts appartenant à l’application et rejetez les autres. Examinez les types, convertisseurs, constructeurs, setters et callbacks autorisés. Le binder limite la résolution sans rendre les types arbitraires inoffensifs. Si vous contrôlez le protocole, préférez None et une sélection explicite.
FAQ
Pas à lui seul. Auto peut lire $type à la désérialisation. Utilisez TypeNameHandling.None ou un ISerializationBinder strict qui n’autorise que des types examinés.
Oui, en opt-in, avec un discriminateur et des types dérivés déclarés dans le code, comme [JsonDerivedType] sous .NET 7+. Le code borne l’ensemble plutôt que des noms CLR arbitraires dans la charge utile.
Recherchez TypeNameHandling, SerializationBinder et JsonConvert.DeserializeObject dans toute la solution. Incluez le démarrage ASP.NET et les paramètres partagés ; suivez les points d’entrée qui transmettent du JSON externe et vérifiez un binder strict sur chaque chemin différent de None.
Références
- Json.NET — Paramètres de sérialisation : TypeNameHandling et SerializationBinder
- API Json.NET — ISerializationBinder
- Microsoft Learn — Polymorphisme dans System.Text.Json
- CWE-502 — Désérialisation de données non fiables
- FlawOpen — BinaryFormatter .NET est-il sûr ?