Identificando código C inseguro com Valgrind e corrigindo-o com Snyk Code
24 de setembro de 2024
0 minutos de leituraC e C++ continuam sendo fundamentais para o desenvolvimento de softwares essenciais. Essas linguagens são usadas em uma ampla variedade de sistemas, de dispositivos embarcados a aplicações de alto desempenho na indústria, na tecnologia operacional (OT) e no setor industrial. Sua eficiência, o controle dos recursos do sistema e o desempenho fazem delas ferramentas indispensáveis para desenvolvedores que trabalham em projetos de missão crítica.
C e C++ são especialmente comuns no Japão, onde os setores de manufatura e industrial são importantes motores da economia. Desenvolvedores japoneses usam essas linguagens para criar softwares robustos e eficientes que sustentam tudo, de sistemas automotivos à automação de fábricas. A precisão e a confiabilidade de C e C++ são essenciais para manter os altos padrões exigidos nesses setores.
A importância da segurança do código em C e C++
Embora C e C++ ofereçam controle e desempenho incomparáveis, também apresentam desafios significativos de segurança. A ausência de recursos de segurança integrados, como o gerenciamento automático de memória, deixa essas linguagens suscetíveis a vulnerabilidades como estouros de buffer, uso após liberação e vazamentos de memória. Embora possam parecer simples e até ingênuas, essas vulnerabilidades podem ter consequências graves, especialmente em softwares essenciais, nos quais confiabilidade e segurança são fundamentais.
Código C vulnerável causa vazamento de memória
Vamos analisar um exemplo de código C vulnerável que desenvolvedores podem escrever e que introduz uma vulnerabilidade de segurança relacionada a vazamentos de memória.
Este é o código do nosso programa em C. Você consegue encontrar a vulnerabilidade de segurança?
Este arquivo program1.c contém um exemplo de vulnerabilidade de alocação dinâmica de memória (MISRA Dir 4.12, MISRA Rule 21.3). A vulnerabilidade de segurança na função allocateMemory() é que ela usa malloc() para alocar memória, mas não a libera, causando um vazamento de memória. É possível evitar isso seguindo as diretrizes MISRA, que restringem a alocação dinâmica de memória.
Esse é um erro comum na programação em C e pode fazer com que seu programa use cada vez mais memória. Com o tempo, isso pode esgotar a memória e causar uma falha no programa ou impedir que outros programas do sistema tenham memória suficiente.
Por que não usar simplesmente a alocação estática de memória, como int arr[10]? Porque, em algumas situações, não é possível alocar memória na pilha. Por exemplo, imagine que você esteja escrevendo uma função para ler um arquivo para a memória. Como você só descobre o tamanho do arquivo durante a execução, não pode usar um array de tamanho fixo. Em vez disso, depois de saber o tamanho do arquivo, você pode usar malloc para alocar exatamente a quantidade necessária de memória.
Compile o programa e, em seguida, execute-o:
Há um vazamento de memória no programa? Como você pode corrigi-lo?
Encontre a vulnerabilidade de segurança em C com Valgrind
Valgrind é uma ferramenta poderosa para encontrar vazamentos de memória no seu programa. Podemos executá-lo com o Valgrind para verificar se há algum vazamento.
Instale o Valgrind no seu sistema. Se você usa um sistema baseado em Linux, pode instalá-lo com o gerenciador de pacotes. Veja um exemplo para sistemas baseados em Debian:
Observação: se você usa o macOS em um dispositivo com chip ARM, o Valgrind não oferece suporte. Nesse caso, vamos ignorar essa etapa e executá-lo em um contêiner do Docker:
Em seguida, execute o contêiner e mapeie o diretório atual para o diretório /tmp do contêiner:
Em seguida, compile o programa program1.c dentro do contêiner:
Depois, podemos executar o programa com o Valgrind para verificar se há vazamentos de memória:
Em seguida, você verá a saída do Valgrind indicando o vazamento de memória:
O Valgrind é ótimo, mas, para quem desenvolve em C no dia a dia, esse fluxo de trabalho não é escalável e exige compilar e construir um programa completo para analisá-lo.
Snyk Code ajuda você a identificar essa vulnerabilidade na sua base de código sem precisar passar pelo processo de compilação. Basta instalar a extensão e abrir o arquivo para que a vulnerabilidade seja exibida. Isso é possível porque Snyk Code é uma ferramenta de análise estática de código que usa técnicas de aprendizado de máquina para identificar problemas diretamente no código, sem exigir uma etapa de build e compilação. Com essa abordagem, quando a Snyk analisa seu código em busca de vulnerabilidades de segurança, você conta com um ciclo de feedback rápido e confiável, com poucos falsos positivos.

Detectando path traversal, estouro de buffer e outras vulnerabilidades em C
O mecanismo SAST que alimenta o Snyk Code detecta muito mais tipos de vulnerabilidade do que apenas vazamentos de memória causados por malloc.
Vamos ver um exemplo mais complexo que combina várias práticas inseguras de programação em C e introduz vulnerabilidades de segurança:
O programa em C acima está repleto de vulnerabilidades, mas é uma forma bastante concisa e simplificada de apresentar código inseguro por questão de brevidade. Ainda assim, algumas práticas de codificação sutis podem facilmente acabar em bases de código reais.
Depois de compilar o programa, você pode executá-lo:
Se houver um arquivo chamado text.txt no mesmo diretório e ele não estiver vazio, o programa lerá o arquivo e exibirá seu conteúdo.
Por exemplo:
Parece tudo certo. O que acontece se você passar um arquivo cujo caminho percorre a estrutura de diretórios?
O programa tem uma vulnerabilidade de path traversal, que permite que um invasor leia arquivos confidenciais no sistema.
Para testar outras vulnerabilidades, experimente:
Passar um arquivo que não existe
Passar um arquivo vazio
Passar o nome ou o caminho completo de um arquivo longo demais (com mais de 50 caracteres)
Alguns desses problemas de segurança vão muito além dos conhecimentos de programação em C de um desenvolvedor. É o caso do path traversal, que exige conhecimento de segurança de aplicações, além de práticas de gerenciamento seguro de memória e experiência consolidada em desenvolvimento com C.
A boa notícia é que, quando você cola o código do programa no IDE, a extensão da Snyk analisa o código C em busca de práticas inseguras e problemas comuns de segurança de aplicações. Ela apresenta os resultados rapidamente, com o contexto do código exibido em linha:

Proteja seu código C e C++ com a Snyk
Uma violação de segurança nos setores de manufatura e industrial pode ter consequências catastróficas, incluindo paralisações operacionais, riscos à segurança e perdas financeiras. Garantir a segurança do código em C e C++ não é apenas uma boa prática: é uma necessidade. Snyk oferece aos desenvolvedores os recursos necessários para identificar e corrigir vulnerabilidades logo no início do processo de desenvolvimento.
Proteja seu código com inteligência de ponta
Conheça toda a gama de recursos de análise estática (SAST) do Snyk Code em apenas 30 minutos.


