Skip to main content

Por trás da divulgação: a vulnerabilidade Zip Slip

Public Disclosure of Critical Arbitrary File Overwrite Vulnerability Zip Slip

15 de agosto de 2018

0 minutos de leitura

Em junho de 2018, a equipe de pesquisa da Snyk encontrou várias ocorrências exploráveis da vulnerabilidade Zip Slip em diferentes ecossistemas, afetando milhares de aplicações. Uma vulnerabilidade tão disseminada exige um processo de divulgação privada bem planejado, para que bibliotecas e projetos vulneráveis sejam alertados sobre sua exposição antes da divulgação pública. Mas como encontrar, corrigir e divulgar uma vulnerabilidade desse tipo para tantas pessoas sem torná-la pública? Neste artigo, contamos em detalhes o que fizemos ao longo de todo o processo, da descoberta à divulgação, passando pela criação de PRs com correções e muito mais.

É importante ressaltar que a Zip Slip não é uma vulnerabilidade específica de um pacote ou biblioteca, mas um tipo de vulnerabilidade que permite a gravação arbitrária de arquivos e é extremamente comum em muitos projetos. Vale mencionar também que a Zip Slip não é uma vulnerabilidade nova, propriamente dita: esse tipo de vulnerabilidade existe há muitos anos, até décadas. Mas, diante de sua prevalência e do número de exemplos vulneráveis encontrados pela nossa equipe de segurança, achamos justo dar um nome a ela, assim como fizemos com a vulnerabilidade Zip Bomb.

O começo

Por que não começar pelo começo? No início de 2018, como parte de nossa pesquisa contínua, identificamos um padrão vulnerável na forma como clientes FTP lidam com downloads de pastas e encontramos uma implementação explorável no Apache Hive. Isso mostra que uma vulnerabilidade já conhecida, que afetava clientes FTP em 1990 (e antes), ainda existe em muitas bibliotecas de clientes FTP de código aberto escritas em diferentes linguagens. Depois, continuamos a encontrar padrões semelhantes em outras bibliotecas de código aberto amplamente utilizadas.

Decidimos começar pela extração de arquivos compactados. Ao extrair arquivos de um arquivo compactado, pode haver um vetor de ataque que permite a travessia de diretórios. A premissa de uma vulnerabilidade de travessia de diretórios é que um invasor consegue acessar partes do sistema de arquivos fora da pasta de destino, onde os arquivos deveriam ficar. Em seguida, o invasor pode sobrescrever arquivos executáveis e executá-los remotamente ou esperar que o sistema ou um usuário os execute, conseguindo assim executar comandos remotamente na máquina da vítima. A vulnerabilidade também pode causar danos ao sobrescrever arquivos de configuração ou outros recursos confidenciais, e pode ser explorada tanto em máquinas clientes (usuários) quanto em servidores.

Saída do terminal mostrando entradas do arquivo compactado, incluindo um caminho de travessia até /tmp/evil.sh

Encontrando bibliotecas exploráveis

A equipe começou analisando várias amostras de código de bibliotecas populares de código aberto nos ecossistemas Java, JavaScript e Go. Não foi preciso investigar muito e, para nossa surpresa, descobrimos que mais da metade era vulnerável. Isso significa que mais da metade das bibliotecas analisadas inicialmente não higienizava nem validava os nomes de arquivos presentes nos arquivos compactados. Quando explorada, essa falha pode levar à sobrescrita arbitrária de arquivos. A lista completa está disponível aqui.

Desde o início, ficou claro que algumas linguagens eram mais afetadas do que outras por essa vulnerabilidade, enquanto em outras ela praticamente não existia. Vamos analisar alguns ecossistemas para entender como as diferentes abordagens à funcionalidade de gerenciamento de arquivos compactados influenciaram a prevalência da vulnerabilidade Zip Slip.

Zip Slip em Java

Por exemplo, o ambiente de execução do Java oferece as classes Zip como parte da linguagem principal, permitindo que desenvolvedores escrevam código para ler arquivos compactados e extrair arquivos ZIP. Bibliotecas Java populares, como Apache Commons-Compress, oferecem suporte a outros formatos, o que amplia o problema. Mas não há uma API simples que faça isso em uma única chamada, levando a muitas implementações diferentes pelo ecossistema, a maioria vulnerável.

Zip Slip em Python

Já o Python oferece a classe zipfile no ambiente de execução principal (zipfile.extractall()) e não é vulnerável. Por isso, durante nossa análise de repositórios Python, encontramos repetidamente implementações seguras.

Vale observar que o tarfile do Python ainda é afetado. Isso acontece porque a implementação do ambiente de execução principal é vulnerável. Quando uma vulnerabilidade está no ambiente de execução principal de uma linguagem, e não em uma biblioteca, ela pode ser corrigida automaticamente quando a aplicação é atualizada para uma versão mais recente da linguagem, sem que seja necessário alterar a aplicação ou suas dependências. Isso costuma acontecer com mais frequência do que desenvolvedores atualizando para uma versão mais recente de uma dependência — a menos, é claro, que você use uma ferramenta como a Snyk para ajudar nisso! (Desculpe, não resisti à propaganda!)

Quem mais é vulnerável?

Logo ficou evidente o quanto algumas das principais linguagens e bibliotecas eram afetadas. Por isso, decidimos concentrar nossa atenção nos projetos de código aberto que não eram bibliotecas. Analisamos os projetos Java de código aberto mais populares hospedados no GitHub que continham código para manipular arquivos compactados.

Percebemos rapidamente que a maioria das implementações continha a vulnerabilidade. Isso era mais comum em Java, onde encontramos as mesmas implementações vulneráveis sendo reutilizadas. Isso indicava que esses trechos vulneráveis eram copiados de outros projetos, da documentação ou de comunidades.

StackOverflow: o mercado das vulnerabilidades

Ao analisar o maior recurso disponível para quem desenvolve copiando e colando código, logo ficou claro que nossa hipótese estava certa. Encontramos muitas perguntas sobre a melhor forma de extrair arquivos de arquivos compactados por meio de código. Também descobrimos que quase todas as respostas no StackOverflow eram vulneráveis. O mais preocupante é que todas as respostas vulneráveis tinham tantos votos positivos que nem dava para contar. Estas são algumas das nossas favoritas, incluindo alguns comentários que alegraram nosso dia:

Depois que iniciamos a divulgação privada, nossa equipe de segurança continuou pesquisando e encontrando outros exemplos dessa vulnerabilidade. Estas são algumas das principais estatísticas que resumem o que encontramos:

  • 12 bibliotecas vulneráveis. Abrimos 5 PRs com correções, que foram integradas.

  • 5 bibliotecas sem uma API de alto nível.

  • Milhares de aplicações com a implementação vulnerável (não necessariamente explorável).

É errado ficar empolgado?

O papel de quem pesquisa segurança é encontrar vulnerabilidades, fechar brechas e ajudar a tornar o mundo do software um lugar seguro, onde bilhões de pessoas possam confiar que transações comerciais essenciais serão concluídas a cada segundo, todos os dias. Isso não significa que descobrir uma vulnerabilidade crítica não seja gratificante. Os momentos de eureka que surgem de tempos em tempos em qualquer trabalho ajudam a manter o foco e a precisão durante as etapas menos empolgantes. Saber que uma descoberta interessante ou uma exposição pode estar logo ali motiva a passar dias, semanas e meses pesquisando. Encontrar uma vulnerabilidade é parecido com a euforia que uma pessoa desenvolvedora sente ao finalmente descobrir a causa raiz de um bug complexo. Ou talvez ao redesenhar uma aplicação para dobrar o desempenho ou triplicar a escalabilidade.

Quando descobrimos a primeira ocorrência da vulnerabilidade Zip Slip em um projeto grande, ficamos muito empolgados. Foi nosso momento de eureka. Mas, quando descobrimos que todas as outras aplicações tinham uma implementação vulnerável, ficamos extremamente surpresos. Percebemos que essa vulnerabilidade não afetava apenas algumas aplicações, mas inúmeros projetos em diferentes ecossistemas.

Investigar todos os dados, entender por que determinadas linguagens eram mais afetadas e como trechos de código vulneráveis se espalhavam pelos projetos de código aberto foi realmente empolgante e esclarecedor. Também era uma tarefa de pesquisa totalmente diferente da busca por vulnerabilidades. O trabalho de verdade começou com a divulgação e a ajuda aos projetos para corrigir o código vulnerável: encontrar um elo fraco é relativamente fácil, mas fortalecer todos os elos é difícil.

A divulgação

Seguimos o processo de divulgação responsável e escolhemos 5 de junho como data para a divulgação pública. Isso deu aos responsáveis pela manutenção dos projetos 60 dias para corrigir os problemas. Como todos os projetos vulneráveis que encontramos eram de código aberto, a atividade nos repositórios, como commits e pull requests, também é pública e visível. Por isso, era importante equilibrar um prazo razoável para corrigir os problemas com o risco de uma ampla exposição pública, que colocaria em perigo os projetos ainda sem correção.

Nosso primeiro passo foi entrar em contato com as pessoas responsáveis pela manutenção das bibliotecas mais utilizadas que apresentavam a vulnerabilidade e informá-las sobre o problema. Enviamos mensagens a 10 bibliotecas nessa primeira leva de e-mails. Algumas pessoas nem sabiam que a biblioteca que haviam criado para uso próprio se tornara uma das mais populares para extração de arquivos. Das 10 bibliotecas, 5 responsáveis pela manutenção pediram ajuda para corrigir o problema. Então, abrimos pull requests com correções (plexus archiver, mholt/archiver, adm-zip, unzipper e zip4j).

Pull request do GitHub que descreve uma vulnerabilidade Zip Slip capaz de extrair arquivos fora do diretório pretendido, com um exemplo de código Java.

Depois de conversar com as pessoas responsáveis pelas bibliotecas, passamos aos projetos afetados que implementaram sua própria lógica de extração, em vez de usar uma biblioteca centralizada. Esse código provavelmente foi escrito do zero ou copiado e colado da documentação, do StackOverflow ou de outros projetos de código aberto. Qualquer uma dessas possibilidades poderia levar à disseminação do código vulnerável. Assim que criamos uma lista, percebemos que havia projetos demais para contatar sem correr o risco de um vazamento público, seja por meio das correções dos projetos, seja por pessoas irresponsáveis que compartilhariam a informação sem entender as consequências. Inicialmente, nos concentramos nos principais projetos, começando pelo Apache, que tinha 15 projetos com implementações vulneráveis.

Depois de uma conversa com Mark J Cox, membro fundador da Apache Software Foundation e responsável pela segurança do Apache, criamos uma planilha colaborativa com todos os projetos possivelmente afetados, para que a equipe deles pudesse fazer a triagem interna e decidir quais eram exploráveis. Mesmo quando não eram exploráveis, corrigir a implementação vulnerável continuava sendo uma boa prática, e quase todos fizeram isso, devido ao risco de ela ser usada no futuro ou copiada para outros projetos. Apache Hadoop, Storm, Hive, Maven e Ant foram identificados como afetados. CVEs públicos (CVE-2018-8008, CVE-2018-8009) foram criados na época da divulgação pública, assim como um comunicado sobre Zip Slip do Maven no site do Apache. Mark colaborou muito conosco e nos ajudou a investigar, corrigir e comunicar o problema a cada um dos projetos Apache afetados.

Também entramos em contato com a Pivotal (a integração do zip foi corrigida em até dois dias após a divulgação!), a Oracle, o verificador de dependências OWASP (corrigido em até um dia após a divulgação!) e muitos outros.

Por fim, queríamos informar em particular todos os outros projetos afetados. Como havia projetos demais para uma única equipe testar e avaliar manualmente, optamos por automatizar o processo: avisamos os mantenedores sobre o possível risco e pedimos que verificassem por conta própria se seus projetos eram realmente exploráveis. É claro que essa divulgação em massa e em maior escala também traz o risco de chamar a atenção do público. Um dos projetos que não era vulnerável recorreu ao Twitter, o que exigiu conversas privadas adicionais para que a publicação fosse removida.

Além da divulgação pública

Quando o problema se tornou público, publicamos uma página informativa, com exemplos de vulnerabilidades, correções sugeridas e muito mais. Criamos um repositório colaborativo no GitHub para informar a comunidade sobre as bibliotecas e os projetos afetados e permitir que ela contribuísse, adicionando bibliotecas e projetos que não havíamos incluído. No último mês, várias bibliotecas e projetos foram adicionados, incluindo closure, sharpziplib, quazip e outros.

Se quiser saber mais sobre a divulgação do Zip Slip, receber orientações sobre divulgação responsável ou contar com a ajuda da Snyk em uma divulgação privada, entre em contato pelo endereço security@snyk.io. Teremos o maior prazer em ajudar a tornar o código aberto mais seguro — um commit de cada vez.

Comece a jogar Capture the Flag

Aprenda a resolver desafios de Capture the Flag assistindo à gravação sob demanda do nosso workshop virtual introdutório.