FlawOpen

flawopen.com/Desserialização insegura/.NET BinaryFormatter: segurança

O BinaryFormatter do .NET é seguro?

CWE-502: Deserialization of Untrusted DataPágina de referência
Resposta curta — não há configuração segura

A Microsoft afirma que BinaryFormatter é inseguro e não pode ser tornado seguro. Recomenda parar de usá-lo mesmo quando o aplicativo acredita que os dados são confiáveis. No .NET 9, os tipos da API continuam presentes, mas a implementação integrada sempre lança PlatformNotSupportedException; runtimes antigos e o pacote de compatibilidade sem suporte ainda têm o risco original.

ARRISCADO
// Não desserialize dados que cruzam uma fronteira de confiança.
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

public static class LegacyReader
{
    public static object Deserialize(Stream input) =>
        new BinaryFormatter().Deserialize(input);
}

// Outros formatadores polimórficos irrestritos a remover:
SoapFormatter
NetDataContractSerializer
LosFormatter
ObjectStateFormatter  // usado internamente no ViewState do ASP.NET

// SerializationBinder não torna esses formatos seguros.
MIGRAR
// A forma dos dados é declarada pelo código da aplicação.
// 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)
    {
        // Limite o tamanho da entrada e valide as regras da aplicação.
        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;
    }
}

// Para arquivos NRBF antigos, use NrbfDecoder para inspecionar
// registros e mapear valores permitidos para um DTO.
// Nunca recrie tipos arbitrários do runtime.

Por que BinaryFormatter é perigoso

BinaryFormatter.Deserialize reconstrói grafos de objetos a partir de um fluxo e pode permitir que dados controlados por um atacante influenciem o fluxo de execução. A Microsoft alerta para negação de serviço, divulgação de informações e execução remota de código. O problema central é a desserialização polimórfica irrestrita: os dados serializados podem influenciar quais tipos e estados de objetos serão processados. Nenhuma opção do formatador o transforma em um analisador seguro de bytes não confiáveis.

O risco não se limita a endpoints HTTP públicos. Arquivos, cache, filas, registros de banco, mensagens de clientes desktop e estado sincronizado na nuvem podem ser influenciados por um atacante posteriormente. Rastreie como os bytes entram e circulam no sistema; “nós gravamos isso” ou “é interno” não é uma classificação permanente de confiança.

Por que SerializationBinder não resolve

Um SerializationBinder personalizado pode restringir os tipos que o formatador tenta resolver, mas a Microsoft diz explicitamente que binder ou outra opção de configuração não mitigam ataques de negação de serviço e podem ser insuficientes contra outras classes de ataque. Binder não substitui a migração; não aceite entrada não confiável enquanto aguarda a remoção do BinaryFormatter.

Localize usos antigos e caminhos relacionados

Pesquise no código, nas referências dos projetos e na configuração do runtime por BinaryFormatter, IFormatter, SoapFormatter, NetDataContractSerializer, LosFormatter e ObjectStateFormatter. Inspecione provedores de sessão, adaptadores de cache, consumidores de filas, importação/exportação de arquivos e aplicações ASP.NET Web Forms antigas. O ViewState normalmente é protegido por código de autenticação de mensagem (MAC); mantenha essa proteção ativa e proteja a machine key. Esse MAC não torna segura a desserialização genérica com BinaryFormatter.

Planeje a migração pelo formato e pela versão do runtime

Para novos dados, escolha um contrato explícito como System.Text.Json, DataContractSerializer, MessagePack ou protobuf-net conforme compatibilidade e formato; não há substituto direto. Para manter dados NRBF antigos, o NrbfDecoder do .NET 9 pode decodificar registros sem instanciar os tipos codificados. Valide a estrutura decodificada e mapeie somente valores esperados para DTOs da aplicação. Revise separadamente as orientações de migração de recursos, área de transferência e arrastar-e-soltar do WinForms/WPF.

Perguntas frequentes

Só desserializamos dados que nós mesmos gravamos. Tudo bem?

A Microsoft recomenda migrar mesmo quando os dados parecem confiáveis, pois armazenamento, cache, arquivos, sincronização e serviços posteriores podem cruzar limites de confiança. Identifique quem pode gravar em cada origem e pare de usar BinaryFormatter em vez de depender dessa suposição.

O que acontece ao migrarmos para .NET 9?

No .NET 9, os tipos da API continuam, mas a implementação integrada sempre lança PlatformNotSupportedException, independentemente do antigo sinalizador de compatibilidade. Audite os usos e migre antes da atualização. Um pacote de compatibilidade sem suporte restaura a implementação vulnerável e não corrige a segurança.

Json.NET é uma substituição segura?

Por padrão, Json.NET define TypeNameHandling como None, evitando que metadados do payload selecionem tipos CLR arbitrários. Não habilite outros valores para entrada não confiável. Se precisar de polimorfismo, use uma lista permitida controlada pela aplicação e siga a orientação da biblioteca. Consulte TypeNameHandling é seguro?

Fontes e referências

Veja também Desserialização insegura: riscos e correção ObjectInputStream Java: desserialização segura Newtonsoft.Json TypeNameHandling: configuração segura? 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