Como padrões inseguros do npm podem roubar seus atalhos de teclado no macOS
28 de junho de 2023
0 minutos de leituraPacotes maliciosos do npm e seus perigos são tema frequente de discussão — sejam centenas de pacotes de malware Cobalt Strike de comando e controle, typosquatting ou malware em geral publicado no registro do npm (incluindo PyPI e outros). Para ajudar desenvolvedores e mantenedores a se protegerem desses riscos de segurança, a Snyk publicou um guia de boas práticas de segurança para o npm.
Dito isso, o escopo do ataque a seguir, sobre o qual Yagiz Nizipli alertou mantenedores de longa data, e o risco real de comprometimento de dados são um ótimo exemplo da importância de minimizar os riscos de execução arbitrária de comandos por gerenciadores de pacotes, como ocorre por meio dos hooks de ciclo de vida postinstall do npm.
Scripts de ciclo de vida do npm
O Node Package Manager (npm) oferece um conjunto de scripts para que desenvolvedores e mantenedores de pacotes gerenciem os eventos do ciclo de vida de um pacote. Esses scripts são muito úteis para desenvolvedores, pois permitem realizar diversas tarefas ou configurações durante a instalação do pacote. Por exemplo, com scripts postinstall, é possível automatizar tarefas como compilar recursos, configurar variáveis de ambiente, executar migrações ou qualquer outra tarefa que possa ser executada automaticamente.
A propriedade scripts de um arquivo package.json define os comandos acionados pelo ciclo de vida do pacote e pelas dependências do pacote em desenvolvimento. Atualmente, o npm oferece suporte a um número limitado de scripts de ciclo de vida em qualquer propriedade scripts de um arquivo package.json.
Para simplificar, o restante deste artigo se concentra no comando postinstall. No entanto, todos os conceitos apresentados também se aplicam a outras operações de ciclo de vida.
Incidentes de segurança anteriores
Vários incidentes de grande repercussão tiveram impacto real sobre desenvolvedores JavaScript, incluindo:
O incidente de segurança do cross-env, descoberto por Oscar Bolmsten.
O ataque liderado por meio do event-stream contra desenvolvedores de aplicativos de criptomoedas.
Vários outros incidentes de segurança envolvendo JavaScript e Node.js estão reunidos no repositório Awesome Node.js Security.
Segurança dos dados armazenados
Profissionais de segurança usam o termo Data-at-rest para se referir à proteção de ativos quando os dados estão armazenados, em contraste com os dados em trânsito ou em processamento. O foco é proteger informações confidenciais armazenadas em bancos de dados, sistemas de arquivos ou armazenamento persistente. A segurança dos dados armazenados busca impedir acesso não autorizado, divulgação ou adulteração dos dados enquanto estão inativos. Há várias medidas para garantir essa segurança, como:
Descriptografia sob demanda: descriptografe apenas os dados necessários para a tarefa em andamento e mantenha os demais criptografados para impedir o acesso não autorizado.
Lógica de controle de acesso: valide a identidade de quem solicita acesso por meio de mecanismos como senha, autenticação de dois fatores ou biometria fornecida pelo sistema operacional (como o Face ID), limitando a exposição do recurso a pessoas não autorizadas.
A superfície de ataque de um desenvolvedor
As boas práticas do setor nos orientam a seguir princípios no desenvolvimento de aplicativos. Elas oferecem muitas vantagens para o trabalho de diferentes equipes e desenvolvedores, mas também ampliam a superfície de ataque.
Que tipo de dado fica armazenado sem criptografia na máquina de um desenvolvedor?
Variáveis de ambiente em arquivos de texto simples, como
.env(disponíveis para uso pelo pacotedotenv).Arquivos de configuração de projetos armazenados como JSON, como
config.json.Chaves SSH para acessar Github/Gitlab, disponíveis na pasta
~/.ssh.E... atalhos de teclado do macOS!
Substituições de texto no macOS
Por padrão, o macOS tem um recurso chamado Text Replacements, oculto no app Preferências do Sistema. Ele permite substituir rapidamente uma palavra por outra. Recentemente, descobri que um desenvolvedor de uma empresa conhecida usava substituições de texto para trocar a palavra-chave @card pelos dados do cartão de crédito. Embora o número do cartão, sem a data de validade nem o CVV, não permita que terceiros usem seu dinheiro, isso amplia a superfície de ataque que eles podem explorar.

Exfiltração das substituições de texto do teclado
Os atalhos de teclado são armazenados em defaults, que corresponde a um arquivo .plist no sistema de arquivos, em algum lugar da sua pasta local. Ao executar o comando a seguir, você verá as substituições de texto configuradas, que também podem ser consultadas no app Preferências do Sistema.
Lembre-se de que o código a seguir não precisa de acesso sudo e pode ser executado por qualquer processo no seu computador.
O mesmo comando pode ser executado por meio de execSync no Node.js e analisado sem dificuldade usando a operação de ciclo de vida postinstall, compatível com o gerenciador de pacotes npm.
Veja um exemplo de script Node.js que agentes maliciosos podem usar para acessar as substituições de texto do macOS e exfiltrar dados confidenciais:
Para garantir que o código acima seja executado quando o pacote for instalado, atualize o arquivo de manifesto do pacote package.json da seguinte forma:
Quando distribuída pelo npm e baixada por um desenvolvedor, esta biblioteca executa diretamente nosso script personalizado para recuperar e processar as substituições do teclado. Se você não prestar atenção, é fácil deixar passar a linha > node ./retrieve.js.
Proteção
Como desenvolvedor, o que você pode fazer para reduzir os riscos de segurança de pacotes maliciosos do npm e os riscos gerais da execução arbitrária de comandos por pacotes na sua árvore de dependências?
Ignore scripts durante a instalação de pacotes do npm
É possível se proteger de pacotes que usam scripts postinstall. O npm oferece a opção de configuração --ignore-scripts durante a instalação de pacotes.
Use configurações padrão seguras no npm
O gerenciador de pacotes npm também tem um arquivo de configuração chamado .npmrc. Você pode alterar as preferências padrão usando a CLI do npm para garantir configurações seguras:
Armazenamento seguro
Acima de tudo, nunca armazene informações confidenciais em texto simples. Se precisar armazená-las assim por outros requisitos, sempre restrinja o acesso ao recurso com autenticação multifator.
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.
