Por trás do C: um olhar sobre vulnerabilidades de C/C++ no universo Python
Aviad Hahami
28 de abril de 2022
0 minutos de leituraEmbora a maioria dos desenvolvedores — eu inclusive — escreva principalmente em linguagens de alto nível, como Python ou JavaScript, às vezes é necessário adicionar elementos nativos para melhorar o desempenho ou outros aspectos do projeto. Como essas chamadas a extensões nativas costumam ser escritas em C ou C++, um projeto que usa principalmente JavaScript ou Python também precisa levar em conta possíveis dependências transitivas de C/C++.
Em maio de 2021, a Snyk adquiriu a FossID, especializada em detectar licenças e vulnerabilidades no ecossistema de código aberto de C e C++. A FossID foi então integrada à Snyk CLI, que passou a poder analisar dependências de C e C++.
Como integrante da equipe de segurança da Snyk, pesquisei os resultados das análises de arquivos C da Snyk em projetos npm e PyPI e encontrei descobertas interessantes — e potencialmente preocupantes.
Nesta publicação, vamos falar dos benefícios que levam desenvolvedores a incluir extensões nativas de C e C++ em projetos escritos em linguagens de alto nível. Em seguida, usaremos Python e o registro PyPI para detectar vulnerabilidades ocultas relacionadas a C nesses projetos e mostrar como vulnerabilidades de baixo nível podem afetar códigos de alto nível aparentemente seguros.
Por que incluir arquivos C/C++ em um projeto de linguagem de alto nível?
Usar arquivos C em um contexto de linguagem de alto nível nem sempre é simples, mas há bons motivos para incluir código C no seu aplicativo.
Execução e desempenho
Pense em uma linguagem interpretada como Python. Toda vez que executamos um programa Python, precisamos analisar e interpretar o código antes de executá-lo. Ao introduzir C nessa combinação, o Cython — um superconjunto de Python e C — permite transpilar o código Python para C e compilá-lo depois, acelerando a execução.
Hardware, recursos e gerenciamento de memória
Às vezes, escrevemos programas que exigem processamento computacional intenso e interagem com hardware especializado. É o caso, por exemplo, de mecanismos gráficos ou softwares relacionados a criptomoedas que podem interagir com a GPU. Também precisamos considerar componentes em tempo real que talvez tenham recursos limitados. Esses casos são sensíveis a operações não determinísticas, como a coleta de lixo, e exigem gerenciamento determinístico de memória — por isso, C é nossa linguagem preferida.
Lemas e hipótese
Nossa hipótese de pesquisa é a seguinte:
Lemas:
Há muitos bons motivos para incluir arquivos C/C++ no código-fonte e nos ambientes de execução de linguagens de alto nível.
Não existe um sistema universal de gerenciamento de pacotes para arquivos C/C++.
Hipótese:
Se analisarmos pacotes de linguagens de alto nível que integram arquivos C, poderemos encontrar vulnerabilidades de C ou originadas em C nesses pacotes.
Para testar nossa hipótese, escolhemos Python e o ecossistema PyPI como primeira opção e teste de viabilidade.
O registro PyPI: C em Python
No momento em que este texto foi escrito, havia cerca de 367.755 bibliotecas disponíveis publicamente no PyPI.
Nossa análise inicial buscou encontrar todos os pacotes (e suas versões) que contêm arquivos C.
Encontramos cerca de 6.200 bibliotecas com pelo menos um arquivo C — aproximadamente 1,7% de todo o ecossistema.
Embora esse número seja pequeno em comparação com o ecossistema inteiro, ele é ideal para os objetivos da nossa pesquisa. Um conjunto menor de resultados facilita a detecção e a eliminação de falsos positivos.
Critério 1: identidade do conteúdo
Primeiro, verificamos a identidade dos arquivos das bibliotecas extraídas na etapa anterior. Nessa análise, testamos cada arquivo C da biblioteca para identificar se ele é ou já foi vulnerável às CVEs que conhecemos.
Graças à incrível tecnologia da FossID, agora parte do produto da Snyk, podemos rastrear qualquer arquivo até sua primeira ocorrência e descobrir onde um trecho de código foi encontrado originalmente.
Ao aplicar nosso primeiro critério, encontramos cerca de 64 versões distintas de pacotes que incluem um ou mais arquivos-fonte vulneráveis originaissem alterações. Ao desconsiderar as versões distintas, chegamos a 143 ocorrências de arquivos idênticos e vulneráveis.
Critério 2: similaridade do conteúdo
O segundo critério avaliado foi a similaridade dos arquivos. Neste estudo, isso significa que, embora o conteúdo dos arquivos possa não ser idêntico, o trecho de código crítico relacionado à vulnerabilidade é.
Ao testar esse critério (excluindo o critério 1), encontramos cerca de 231 versões distintas de pacotes com um ou mais trechos sabidamente vulneráveis. Sem considerar as versões distintas, encontramos 1.931 trechos vulneráveis idênticos.

Analisando os números
Consolidando os números acima, encontramos cerca de 2.074 ocorrências dos nossos critérios em pacotes do PyPI. Como o código C costuma ser usado em tarefas de engenharia mais complexas, não nos surpreendemos ao encontrar bibliotecas de baixo nível nos resultados, como:
gevent (5,7 mil)
pycrypto (2,4 mil)
selectolax (cerca de 500)
O gráfico abaixo mostra uma análise detalhada das bibliotecas Python que contêm C. Ele apresenta o total (representado pelo gráfico de pizza), a porcentagem marcada como vulnerável (incluindo casos não exploráveis ou falsos positivos) e a porcentagem que é vulnerável com altíssima probabilidade.
Arquivos C em bibliotecas Python: panorama das vulnerabilidades

Comprovar que vulnerabilidades em bibliotecas podem ser exploradas não é simples nem automático — todas as vulnerabilidades relatadas precisam ser verificadas manualmente. No entanto, para demonstrar as importantes implicações no mundo real do problema que estamos discutindo, a próxima seção apresenta uma vulnerabilidade e a gravidade de sua exploração.
Vulnerabilidade oculta há 20 anos — python-libsbml
Uma das bibliotecas identificadas pela nossa ferramenta foi a python-libsbml, usada para ler, gravar e manipular a linguagem de marcação de biologia de sistemas (SBML). Como essa linguagem de marcação é relacionada a XML, não nos surpreendeu encontrar libxml2 entre as dependências do projeto.
Nossa ferramenta marcou um dos arquivos (parser.c) como vulnerável ao ataque Billion Laughs — uma vulnerabilidade de DoS com 20 anos, catalogada como CVE-2003-1564. O ataque Billion Laughs é bem simples: basta gerar entidades autorreferentes suficientes em um documento XML e enviá-lo ao analisador.
Veja a prova de conceito (PoC) dessa vulnerabilidade.
Crie o payload malicioso e salve-o como payload.xml
Depois de instalar a python-libsbml, crie o seguinte arquivo Python:
Por fim, execute o arquivo Python com:
“Se você seguir as etapas corretamente, o uso da CPU deve chegar a 100% e a memória continuará aumentando até a máquina ficar sem memória (OOM). Assim, executamos um ataque de DoS contra a máquina.”

Essa vulnerabilidade talvez não cause comoção na comunidade de desenvolvimento, mas imagine o que aconteceria se uma vulnerabilidade de BoF, UaF, PE/RCE ou qualquer outra originada em código C estivesse escondida no seu código Python ou NodeJS. Você já verificou se há alguma?
Essa biblioteca é baixada cerca de 20 mil vezes por mês e é uma dependência direta de aproximadamente 115 projetos públicos. Como essa vulnerabilidade de 20 anos já era conhecida, um número impressionante de dependentes desavisados a distribuiu para seus clientes e usuários.
E agora?
Enquanto continuamos a encontrar e divulgar vulnerabilidades para os responsáveis pela manutenção de projetos de código aberto, queremos incentivar desenvolvedores a procurar arquivos C em projetos que não sejam escritos em C.
Como esses arquivos C muitas vezes não contam com gerenciadores de pacotes, costumam permanecer sem alterações (ou ser copiados e colados) por longos períodos e podem acabar desatualizados e vulneráveis — esperamos que sejam identificados por pessoas bem-intencionadas.
Inscreva-se na Snyk hoje mesmo e use o novo recurso da CLI para analisar dependências C/C++ não gerenciadas nos seus projetos.
Comece a resolver desafios de capture the flag
Aprenda a resolver desafios de capture the flag assistindo sob demanda ao nosso workshop virtual introdutório.



