FlawOpen

flawopen.com/Desserialização insegura/TypeNameHandling

Newtonsoft.Json TypeNameHandling: configuração segura para JSON não confiável?

CWE-502: Deserialization of Untrusted DataPágina de referência
Resposta curta

JSON comum descreve dados; seu código escolhe o tipo .NET. Com TypeNameHandling ativado, $type pode influenciar a resolução de tipos durante a desserialização. Use None para entradas não confiáveis. Se precisar de polimorfismo, valide tipos com um ISerializationBinder restrito ou use um mapeamento fechado de discriminadores declarado no código.

VULNERÁVEL
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);
CORRIGIDO
// 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+).

Por que desenvolvedores ativam TypeNameHandling

Dados polimórficos são o motivo comum: uma coleção Shape pode precisar voltar como Circle ou Square. Json.NET lê e grava nomes de tipos por $type. Em entradas não confiáveis, esses metadados podem influenciar o tipo resolvido; o risco depende dos tipos permitidos e do comportamento na desserialização. Uma cadeia perigosa exige um tipo acessível com efeitos colaterais; JSON por si só não basta.

A fronteira de confiança deve funcionar no sentido oposto: o código escolhe um subtipo de um conjunto fechado de discriminadores validados. System.Text.Json oferece polimorfismo opt-in por atributos como [JsonDerivedType]; não ativa nomes CLR arbitrários do JSON. Consulte a orientação sobre BinaryFormatter para uma fronteira relacionada.

Um ISerializationBinder personalizado é suficiente?

Um ISerializationBinder restrito é a defesa exigida pelo Json.NET quando TypeNameHandling não é None para dados externos. Mapeie apenas poucos nomes exatos, pertencentes à aplicação, e rejeite os demais. Revise tipos, conversores, construtores, setters e callbacks. O binder restringe a resolução, mas não torna tipos arbitrários inofensivos. Prefira None e despacho explícito se controlar o protocolo.

Perguntas frequentes

TypeNameHandling.Auto é seguro para JSON não confiável?

Não por si só. Auto pode ler $type durante a desserialização. Use TypeNameHandling.None ou um ISerializationBinder restrito que permita apenas tipos revisados.

System.Text.Json oferece polimorfismo seguro?

Sim, opt-in, com discriminador e tipos derivados declarados no código, como [JsonDerivedType] no .NET 7+. O conjunto é limitado pelo código, não por nomes CLR arbitrários no conteúdo.

Como auditar uma aplicação .NET?

Pesquise TypeNameHandling, SerializationBinder e JsonConvert.DeserializeObject em toda a solução. Inclua inicialização ASP.NET e configurações compartilhadas; rastreie endpoints que passam JSON externo e confirme binder estrito em todo caminho diferente de None.

Referências

Veja também Desserialização insegura: riscos e correção PHP unserialize() e entrada não confiável Segurança do pickle.load() em Python: riscos de dados não confiáveis Ruby YAML.load é seguro? Versões do Psych e safe_load .NET BinaryFormatter: riscos e migração ObjectInputStream Java: desserialização segura