Entenda a vulnerabilidade de segurança de poluição de protótipo no minimist
Kirill Efimov
26 de março de 2020
0 minutos de leituraEm 11 de março de 2020, a Snyk publicou uma vulnerabilidade de segurança de poluição de protótipo de gravidade média (CVE-2020-7598) que afeta o pacote npm minimist. A descoberta faz parte de uma pesquisa contínua da equipe de pesquisa de segurança da Snyk, que já havia encontrado vulnerabilidades semelhantes em outras bibliotecas JavaScript de grande destaque, como lodash e jQuery.
O que é uma vulnerabilidade de poluição de protótipo?
Essa vulnerabilidade de segurança, conhecida como poluição de protótipo, permite que invasores sobrescrevam o protótipo de um objeto de uma aplicação JavaScript. Quando isso acontece, propriedades controladas pelo invasor podem ser injetadas em objetos e causar uma negação de serviço ao disparar exceções em JavaScript ou adulterar o código-fonte da aplicação para forçar a execução do caminho de código injetado pelo invasor.
A pesquisa atual da equipe da Snyk também encontrou vulnerabilidades de segurança semelhantes em outros pacotes npm, alguns tão conhecidos quanto o yargs-parser:

A equipe de pesquisa de segurança da Snyk segue as diretrizes de divulgação responsável e trabalhou com os mantenedores de minimist, yargs-parser e outros pacotes para comunicar nossas descobertas, validá-las e confirmá-las com os respectivos mantenedores, que reconheceram e concordaram que a superfície de ataque era vulnerável.
Agradecemos aos mantenedores que responderam rapidamente e agilizaram a publicação das correções, além de disponibilizarem correções de segurança para versões antigas — por exemplo, a correção de segurança do minimist para versões anteriores à 1.0.0 e a correção de segurança do yargs-parser para versões anteriores à 13.1.2.
Poluição de protótipo em analisadores de CLI
Vale lembrar que não vou explicar neste artigo os conceitos básicos de poluição de protótipo — já existem muitos artigos sobre o tema. Também publicamos no blog um artigo detalhado que oferece uma boa introdução às vulnerabilidades de poluição de protótipo.
Neste artigo, vou abordar:
A natureza dos analisadores de argumentos de linha de comando (CLI) e seu uso comum no ecossistema JavaScript atual.
Mostre como aplicativos que dependem desse tipo de analisador podem ser vulneráveis a ataques de poluição de protótipo, apresentando exemplos reais de pacotes vulneráveis.
Os critérios usados para classificar a gravidade e avaliar o impacto geral dessas vulnerabilidades nos aplicativos.
É só uma biblioteca de argumentos de linha de comando — não seria basicamente alguém atacando a si mesmo?
minimist e yargs-parser são bibliotecas JavaScript criadas para analisar argumentos de aplicativos Node.js de linha de comando. Vamos ver como uma CLI do Node.js pode levar ao aumento local de privilégios por causa de validação inadequada de entrada (CWE-20), uma vulnerabilidade comum com milhares de casos e CVEs documentados.
No exemplo a seguir, vamos criar um utilitário de sistema que permite que usuários sem privilégios de root reiniciem um servidor. Aqui, usamos o minimist com um único objetivo: exibir uma pequena ajuda para a opção de linha de comando --help.
O código a seguir mostra nossa pequena CLI do Node.js, chamada u-reboot:
Para distribuir essa ferramenta incrível de forma mais prática, precisamos compilá-la como um binário independente. Podemos usar pkg para isso:
Por fim, para que funcione, precisamos conceder as permissões adequadas ao binário:
4555 é uma permissão de leitura e execução para todos os usuários e também a permissão setuid. Saiba mais sobre setuid aqui. Em resumo, ela permite executar o binário com as permissões do proprietário (no nosso caso, o usuário root).
Agora temos a ferramenta de linha de comando u-reboot, que qualquer usuário pode executar para reiniciar o servidor ou a estação de trabalho — mas não queremos permitir que façam mais nada no servidor.
Como esse aplicativo de linha de comando pode ser explorado? Lembre-se de que os usuários têm poucos privilégios no servidor e não deveriam conseguir executar outros comandos como root.
Explorando aplicativos de CLI do Node.js
A vulnerabilidade de segurança no minimist permite poluir o protótipo de Object. De repente, u-reboot fica vulnerável a um caso clássico de elevação de privilégios.
Viu uid=0(root) na saída? Agora podemos executar qualquer comando com as credenciais de root explorando a vulnerabilidade de poluição de protótipo no minimist, usado pela CLI u-reboot.
O ataque é possível porque child_peorccess.execSync tem um objeto options com a propriedade opcional shell. Se shell estiver vazio, execSync usará /bin/sh, de acordo com a documentação. Mas, quando poluímos todos os objetos com a propriedade shell definida como /tmp/exploit, execSync usa nosso exploit como shell.
Isso parece uma vulnerabilidade local. Por que você diz que ela tem um vetor de ataque pela rede?
Isso me lembra a vulnerabilidade shellshock, divulgada em 2014. No caso do shellshock, era possível enganar o shell Bash para executar código arbitrário injetado por meio de variáveis de ambiente. Essa vulnerabilidade parece totalmente local (quem mais pode controlar variáveis de ambiente?), mas o shell Bash é usado com muita frequência: vários serviços web o utilizam para processar solicitações, permitindo que um invasor execute comandos arbitrários. Recomendo a leitura desta breve explicação se você ainda não conhece a vulnerabilidade.
Essa vulnerabilidade se limita à elevação de privilégios? Não. Nossa equipe de pesquisa investigou diferentes casos de uso do minimist e do yargs-parser e encontrou alguns exemplos interessantes. Não vou analisar cada caso em profundidade — os exemplos mostram que os analisadores de argumentos de CLI nem sempre são usados da forma que você imagina.
Terminal in React — um componente React que emula um terminal no navegador. Ele usa minimist para analisar os argumentos dos comandos da CLI. Você também pode encontrar outros exemplos de emuladores de terminal.
Os argumentos de bots de conversa costumam parecer argumentos de CLI, não é? Encontramos vários exemplos de pessoas usando analisadores de argumentos de CLI justamente para isso: 1, 2, 3, 4, 5.
apibone — uma biblioteca que oferece algumas interfaces para serviços consultáveis. Ela simplesmente abstrai objetos de solicitação e resposta para as funções definidas. Usa yargs-parser para analisar partes de consultas HTTP.
Se você procurar com atenção, encontrará mais exemplos em repositórios open source do GitHub, com diferentes padrões de uso pouco óbvios.
Esses aplicativos deveriam evitar uma biblioteca como minimist, criada para analisar argumentos de CLI, e reutilizá-la em aplicativos web e de rede? Talvez. Mas, na Snyk, acreditamos que os analisadores são componentes de código que exigem muita responsabilidade. Em geral, eles estão no início do processamento de dados e interagem diretamente com as entradas do usuário.
Além disso, o minimist é uma biblioteca de análise de argumentos de uso geral: não está diretamente vinculado a algo como process.argv do Node.js. Você pode usar o minimist com um array de strings, e ele vai analisá-las como se fossem argumentos de CLI.
Pense nisso: quantos problemas os analisadores de XML causaram? E o mecanismo de desserialização do Java? Um bom exemplo que você talvez conheça é o analisador JSON bourne, criado por Eran Hammer depois que ele lidou com problemas de poluição de protótipo envolvendo hapi e joi. O analisador JSON Bourne foi criado com um único objetivo: proteger contra propriedades __proto__ em um payload JSON. Saiba mais no artigo dele.
Como classificamos a gravidade dessa vulnerabilidade?
Para descrever a vulnerabilidade, atribuímos o seguinte vetor CVSS: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L.
Vetor de ataque — Rede. Encontramos o minimist e o yargs-parser sendo usados em vários bots de conversa e aplicativos web. Mesmo que não seja uma boa prática usar essas bibliotecas nesses casos, não podemos ignorar que isso acontece.
Complexidade do ataque — Alta. As vulnerabilidades de poluição de protótipo só se tornam uma ameaça real se o invasor encontrar um gadget adequado para executar código remotamente ou realizar outra ação necessária para continuar o ataque. No nosso exemplo, a chamada “execSync” funciona como esse gadget.
Privilégios necessários — Nenhum. O invasor precisa conseguir enviar uma string que será interpretada como argumentos de CLI. Não são necessários privilégios especiais.
Interação do usuário — Nenhuma.
Escopo — Inalterado. Acredito que essas duas propriedades não precisam de explicação adicional.
Confidencialidade — Baixa.
Integridade — Baixa.
Disponibilidade — Baixa. Esses três atributos são baixos pelos motivos descritos no item 2: as vulnerabilidades de poluição de protótipo devem ser avaliadas no contexto de um aplicativo.
Essa vulnerabilidade definitivamente não tem gravidade alta (a pontuação CVSS é 5,6 — média), mas nossa equipe de pesquisa identificou claramente vários cenários de ataque. Acreditamos que a popularidade das duas bibliotecas mencionadas exige divulgação adequada e correções.
O que devo fazer agora?
Se você já usa a Snyk para monitorar seus aplicativos e conectou seus repositórios do GitHub ou Bitbucket, provavelmente já recebeu uma solicitação de pull request automatizada da Snyk para atualizar seus projetos para as versões corrigidas das bibliotecas vulneráveis.
Se você ainda não usa a Snyk, pode adicionar seus projetos. A Snyk é gratuita para projetos open source, e você pode importar seus projetos dos repositórios de código para o painel da Snyk.
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.



