Soluções

Cyber Security – Substituindo o BinaryFormatter no .NET

Cyber Security – BinaryFormatter: Um Risco à Segurança

O código fonte do .NET está em constante evolução e sua equipe de desenvolvimento está atenta as questões de Cyber Security, no entanto, classes legadas como o BinaryFormatter continuam a apresentar vulnerabilidades exploráveis por atacantes. Nesta análise, discutiremos a vulnerabilidade crítica associada ao BinaryFormatter registrada pelos códigos CVE-2023-32737, CWE-502, e CA2300 (você pode ler mais nos links), destacando o que são esses problemas, como eles impactam a segurança, e as melhores práticas para mitigá-los.

O que é o BinaryFormatter?

O BinaryFormatter é uma classe do .NET Framework utilizada para serializar e desserializar objetos em formato binário, facilitando o armazenamento ou a transferência de dados complexos. No entanto, devido à forma como o BinaryFormatter trata dados durante a desserialização, ele pode ser suscetível a ataques de desserialização inseguros, onde entradas maliciosas podem executar códigos arbitrários e comprometer a segurança da aplicação.

Cyber Security – Entendendo os Códigos de Vulnerabilidade

CVE-2023-32737: Código de Vulnerabilidade Comum

O CVE-2023-32737 é um identificador específico para uma vulnerabilidade do tipo “desserialização insegura” encontrada no BinaryFormatter. Ele indica que a manipulação de dados serializados possibilita a exploração da classe, permitindo que códigos realizem ações inesperadas e potencialmente maliciosas no ambiente de execução da aplicação.

CWE-502: Categoria de Fraquezas

O CWE-502 refere-se à categoria “Desserialização de Dados Não Confiáveis”. Essa classificação indica que uma vulnerabilidade ocorre quando dados maliciosos são desserializados, o que pode desencadear execuções de código indesejadas. Em outras palavras, o processamento de dados de entrada potencialmente perigosos pode ameaçar a segurança do sistema e comprometer sua integridade.

CA2300: Análise de Código para Segurança

O CA2300 recomenda evitar o processamento direto de dados não confiáveis, garantindo maior segurança no sistema. Esse aviso serve para alertar desenvolvedores durante o processo de construção do software, sinalizando o uso de práticas inseguras, como a desserialização direta de dados de fontes desconhecidas.

Impacto da Vulnerabilidade do BinaryFormatter

Ao utilizar o BinaryFormatter, aplicações correm o risco de receber objetos binários maliciosos que, durante a desserialização, podem executar código indesejado. Essa vulnerabilidade representa uma séria ameaça, pois permite a elevação de privilégios ou a execução de comandos remotamente, comprometendo a integridade do sistema.

Por ser uma biblioteca amplamente utilizada e inclusa no .NET Framework (não confundir com .NET Core, onde o uso do BinaryFormatter já é desaconselhado e possui suporte limitado), muitos sistemas podem ser alvos potenciais, especialmente os que interagem com dados de fontes externas.

Cyber Security – Quatro formas de mitigar o problema do BinaryFormatter

1. Substituindo o BinaryFormatter

  • A Microsoft já recomenda que o BinaryFormatter seja evitado em novos projetos, incentivando o uso de alternativas mais seguras, como o System.Text.Json, XmlSerializer, ou DataContractSerializer.

2. Verificar a Origem dos Dados

  • Garanta que dados serializados são provenientes de fontes confiáveis. Mesmo ao utilizar métodos alternativos de serialização, é importante controlar e garantir a confiabilidade da origem dos dados.

3. Cyber Security – Atualizar o .NET e Aplicar Patches de Segurança

  • A Microsoft lança periodicamente atualizações e patches para corrigir vulnerabilidades. Assegure-se de que o ambiente de desenvolvimento e os aplicativos estejam com as versões mais recentes do .NET Framework.

4. Realizar Análise Estática do Código

  • Ferramentas de análise estática, como o Code Analysis for .NET (que fornece o alerta CA2300), podem identificar o uso de BinaryFormatter e sugerir mudanças antes da implantação da aplicação.

Alternativas Seguras para Serialização

Como parte das melhores práticas, os desenvolvedores podem considerar o uso de serializadores seguros e específicos para os dados e cenários em questão. Algumas das alternativas recomendadas incluem:

  • System.Text.Json: Uma alternativa leve e segura para a serialização JSON.
  • DataContractSerializer: Indicado para cenários de comunicação entre serviços, pois oferece mais controle sobre o que é serializado.
  • Protobuf: Uma alternativa altamente eficiente e segura, principalmente para comunicação entre microserviços.
  • NrbfDecoder: Uma alternativa voltada para a leitura e interpretação de objetos binários que mantém compatibilidade com o BinaryFormatter. É usada para decodificar o formato NRBF (.NET Remoting Binary Format), que permite manipular dados binários sem os riscos de execução de código presentes no BinaryFormatter. Embora não seja uma substituição direta, o NrbfDecoder pode ajudar a migrar dados legados ou analisar binários com segurança. Saiba mais sobre o NrbfDecoder no site da Microsoft.

Cyber Security – Substituindo o BinaryFormatter com o NrbfDecoder

Imagine o cenário onde recebemos via API, dados formatados usando o BinaryFormatter, ou seja, não temos domínio sobre o client mas apenas da API que deserializa esses dados tambem usando o BinaryFormatter.

Este caso categoriza o problema de segurança pois podemos receber um código malicioso entre esses dados. Como podemos resolver nosso lado sem quebrar o contrato com os consumidores de nossas APIs?

Uma opção é usar o NrbfDecoder, uma biblioteca disponível no NuGet. Na data de escrita deste artigo, ela ainda permanece em Release Candidate, embora a Microsoft já a considere em “produção”. Isso ocorre porque sua API ainda deve passar por uma grande atualização.

Vamos explorar abaixo uma solução de desserialização com o NrbfDecoder mencionado anteriormente.

Considere que a classe abaixo foi serializada com BinaryFormatter e recebemos uma MemoryStream contendo esta classe.

public class Employee
{
 public int Id { get; set; }
 public List<string> Roles { get; set; }
}

Vamos ao codigo que desserializa:

...
// Valida se a MemoryStream pode ser desserializada
if (NrbfDecoder.StartsWithPayloadHeader(memoryStream))
{
 memoryStream.Position = 0;
 // Decodifica a instancia de uma classe que não seja um Array ou tipo primitivo
 ClassRecord decodedClass = NrbfDecoder.DecodeClassRecord(memoryStream);
 
 // Iterando sobre as propriedades para fazer bind pelo nome
 foreach (var memberName in decodedClass.MemberNames)
 {
  if (memberName.Equals(nameof(employee.Id))
  {
   // Lidando com tipos primitivos
   employee.Id = decodedClass.GetInt32(memberName);
  }
  
  if (memberName.Equals(nameof(employee.Roles))
  {
   var complexDecoded = decodedClass.GetClassRecord(memberName);
   
   // Identifico o tipo para trata-lo corretamente
   if (complexDecoded.TypeName.FullName.Contains("List[[System.String]]"))
   {
    var listDecoded = complexDecoded.GetArrayRecord("_items")
                    .GetArray(expectedArrayType: typeof(string));
    
    foreach (var item in listDecoded)
    {
     // Se for tipo primitivo
     if (item is not ClassRecord)
     {
      employee.Roles.Add(item);
     }
     
     // Caso não seja tipo primitivo aqui seguimos decodificando as
     // classes ou arrays conforme fizemos anteriormente.
    }
   }
  }
 }
 
 // Ao final temos uma instancia da classe Employee desserializada
 

Conclusão

Embora o BinaryFormatter seja uma ferramenta poderosa no .NET, ele se tornou uma fonte de risco devido à sua suscetibilidade à desserialização insegura, dessa forma a vulnerabilidade identificada pelo CVE-2023-32737 e categorizada em CWE-502 destaca a necessidade de adotar práticas seguras de serialização e controle de dados. Por isso, a Microsoft e a comunidade .NET recomendam substituir o BinaryFormatter por métodos de serialização mais seguros, protegendo assim as aplicações e prevenindo que explorações comprometam a integridade do sistema.

Vinicius Sodré

Formado em Ciência da Computação pela Unicarioca, desenvolvedor de software com 15 anos de experiência em grandes empresas nacionais e multinacionais. Vinicius está à frente deste blog, feito de desenvolvedor para desenvolvedores de iniciantes a experientes.

Compartilhar
Publicado por:
Vinicius Sodré

Posts Recentes

Desvios Condicionais no Python: Controle o Fluxo – Aula 5

Ao desenvolver um software, uma das tarefas mais comuns é controlar o fluxo de execução…

2 semanas atrás

Aprenda manipular Strings no Python – Aula 4

Manipular strings no Python é uma das tarefas mais requisitadas, e o Python oferece ferramentas…

1 mês atrás

Tipos de Dados em Python: Entenda os Tipos Primitivos – Aula 3

Compreender os tipos de dados em Python é um dos primeiros passos para dominar a…

1 mês atrás

Garbage Collector no .NET: Evite Erros e Melhore o Desempenho

O Garbage Collector (GC) é um dos pilares essenciais para o gerenciamento de memória no…

1 mês atrás

Como criar variáveis em Python – Curso de Python Aula 2

Aprender a criar variáveis em Python é um dos passos iniciais para dominar essa linguagem…

2 meses atrás

Curso de Python, aprenda o básico rapidamente – Aula 1

Python está no topo das linguagens de programação mais utilizadas, e isso certamente não é…

2 meses atrás

Este blog utiliza cookies. Se você continuar assumiremos que você está satisfeito com ele.

Leia Mais...