1 pontos por GN⁺ 2024-03-01 | 1 comentários | Compartilhar no WhatsApp
  • A campanha de confusão de repositório (repo confusion), iniciada em meados de 2023, voltou a se espalhar, e mais de 100 mil repositórios com payloads maliciosos semelhantes foram detectados no GitHub
  • Os atacantes criam clones maliciosos parecidos com repositórios legítimos para induzir desenvolvedores ao erro, combinando clonagem, inserção de loader, reenvio, forks em massa e promoção discreta
  • Ao executar o repositório malicioso, após uma ofuscação em 7 etapas, são baixados código Python e binários, e dados sensíveis como credenciais de login, senhas de navegador e cookies são roubados
  • Mesmo que o GitHub remova automaticamente a maioria dos forks, repositórios que escapam da detecção e uploads manuais permanecem; mesmo que apenas 1% sobreviva, milhares de repositórios maliciosos continuam ativos
  • O fluxo de ataque está migrando de pacotes maliciosos no PyPI para repositórios no GitHub, tornando também a cadeia de suprimentos de software fora dos gerenciadores de pacotes uma superfície de ataque direta

Como funciona o ataque de confusão de repositório

  • A confusão de repositório se parece com dependency confusion no sentido de induzir o usuário a baixar um repositório malicioso em vez do legítimo
  • A diferença está no ponto explorado
    • dependency confusion explora o funcionamento do gerenciador de pacotes
    • confusão de repositório depende de uma situação em que a pessoa escolhe por engano um repositório parecido
  • Nesta campanha, repositórios maliciosos foram espalhados em massa no GitHub para aumentar a chance de infecção
    • clona repositórios existentes como TwitterFollowBot, WhatsappBOT, discord-boost-tool, Twitch-Follow-Bot
    • insere um loader de malware no clone
    • reenvia para o GitHub com o mesmo nome
    • faz fork automático de cada repositório milhares de vezes
    • promove discretamente em fóruns e no Discord

Fluxo após executar o repositório malicioso

  • Quando o usuário utiliza o repositório malicioso, o payload oculto desfaz uma ofuscação em 7 etapas
  • Em seguida, baixa código Python malicioso e executáveis binários
  • O código malicioso é baseado principalmente em uma versão modificada do BlackCap-Grabber
  • Os alvos da coleta incluem credenciais de login de vários apps, senhas e cookies de navegador, além de outros dados confidenciais
  • Os dados roubados são enviados ao servidor de C&C (command-and-control) do atacante, e outras atividades maliciosas continuam em seguida
  • A análise do código relacionado pode ser vista na análise técnica da Trend Micro

Remoção automática do GitHub e repositórios que permanecem

  • O GitHub identifica a automação e remove rapidamente a maior parte dos repositórios forkados
  • Ainda assim, muitos repositórios escapam da detecção automatizada, e os enviados manualmente sobrevivem
  • Como a cadeia de ataque é automatizada em larga escala, mesmo que apenas 1% permaneça, isso ainda representa milhares de repositórios maliciosos
  • Ao pesquisar 🔥 2024 language:python no GitHub, é possível ver parte dos repositórios atualmente em disseminação
  • Incluindo os repositórios já removidos, a escala total chega à casa dos milhões
    • a remoção normalmente acontece algumas horas após o upload, o que dificulta a documentação
    • muitos repositórios de origem continuam disponíveis, e a remoção mira principalmente o fork bomb
    • por exemplo, na lista de repositórios de Mattia69 o resumo mostra milhares de forks, mas eles não aparecem no detalhe dos forks
  • Alguns usuários fazem fork de repositórios maliciosos sem saber, criando também um efeito de rede secundário de engenharia social

Linha do tempo da campanha

  • Maio de 2023: a Phylum relatou pacotes maliciosos publicados no PyPI
    • esses pacotes continham a parte inicial do payload atual
    • a disseminação ocorria por chamadas os.system("pip install package") embutidas em forks de repositórios populares do GitHub, como chatgpt-api
  • Julho a agosto de 2023: vários repositórios maliciosos foram publicados no GitHub e passaram a entregar o payload diretamente, em vez de buscar pacotes no PyPI
    • foi uma mudança após o PyPI remover os pacotes maliciosos e a comunidade de segurança aumentar a atenção sobre o caso
    • Aliakbar Zahravi e Peter Girnus, da Trend Micro, publicaram a análise técnica
  • Novembro de 2023 até agora: mais de 100 mil repositórios contendo payloads maliciosos semelhantes foram detectados, e o número continua crescendo
  • É claro por que esse método é vantajoso para os atacantes
    • a escala do GitHub é tão grande que mesmo muitas instâncias ainda parecem poucas em termos relativos, dificultando a detecção
    • diferentemente de antes, não há participação do gerenciador de pacotes, então não fica um nome explícito de pacote malicioso como indicador
    • como os repositórios visados ocupam nichos pequenos e têm baixa popularidade, fica mais fácil para desenvolvedores clonarem por engano um repositório impostor malicioso

Migração de gerenciadores de pacote para SCM

  • A migração de pacotes maliciosos no PyPI para repositórios maliciosos no GitHub acompanha um movimento observado em vários gerenciadores de pacote e plataformas de SCM
  • À medida que a comunidade de segurança passou a focar mais nos gerenciadores de pacote, o caminho do ataque foi deslocado para outro lugar
  • O GitHub e plataformas semelhantes facilitam a criação automatizada de contas e repositórios, além de oferecer APIs convenientes e rate limits frouxos que são fáceis de contornar
  • Como é possível se esconder entre inúmeros repositórios, o SCM se torna um alvo ideal para infectar discretamente a cadeia de suprimentos de software
  • Campanhas de dependency confusion, código malicioso em registros de pacote e disseminação de malware via SCM mostram que, mesmo com muitas ferramentas e mecanismos de segurança, a segurança da cadeia de suprimentos de software continua frágil

Indicadores para verificar infecção

  • No código Python, é preciso procurar os seguintes padrões e investigar qualquer correspondência
    • exec(Fernet
    • exec(requests
    • exec(__import
    • exec(bytes
    • exec("""\nimport
    • exec(compile
    • __import__("builtins").exec(
  • É preciso verificar se há repositórios locais ligados a automação de plataformas sociais, bots e jogos, e removê-los
  • Se for realmente necessário usá-los, reinstale apenas após validar cuidadosamente a origem ou executá-los em um sandbox
  • Se houver possibilidade de ter clonado esse tipo de repositório, deve-se assumir que os seguintes cookies, credenciais e chaves foram roubados e agir de acordo
    • navegadores: serviços financeiros, serviços de e-mail, serviços de criptomoedas, Amazon, eBay, AliExpress, Facebook, Instagram, Twitter, Youtube, Discord, TikTok, Telegram, Twitch, Steam, Yahoo, ExpressVPN, Spotify, serviços de streaming
    • apps: Exodus, Atomic Wallet, Guarda, Coinomi, Ethereum
  • Uma lista completa de checksums de arquivos é impraticável de tratar, mas alguns itens comuns podem ser vistos no gráfico do VirusTotal
  • Após ser notificada, a Cloudflare desativou os registros DNS dos endereços maliciosos encontrados

Defesa e resposta

  • O GitHub foi notificado e removeu a maior parte dos repositórios maliciosos, mas a campanha continua em andamento
  • Ataques que tentam injetar código malicioso na cadeia de suprimentos estão se tornando cada vez mais comuns
  • Existem muitas soluções para detectar malware em nível de sistema e rede, mas a cadeia de suprimentos continua sendo uma superfície de ataque grande e lucrativa para os atacantes
  • Ao encontrar um repositório malicioso, independentemente de fazer parte desta campanha, é possível denunciá-lo pelo relatório de abuso ou spam do GitHub
  • A Apiiro construiu um sistema de detecção de malware para monitorar codebases conectadas
    • análise de código baseada em LLM
    • decomposição do código em um grafo completo de fluxo de execução
    • mecanismo heurístico
    • decodificação, descriptografia e desofuscação dinâmicas
  • Sem monitorar payloads maliciosos injetados, a segurança da organização passa a depender de condições como a capacidade dos desenvolvedores de não escolherem o repositório errado quase idêntico, configuração perfeita de CI/CD sem erros e código de terceiros 100% seguro
  • É necessária uma abordagem que vá além da detecção e coleta tradicional de vulnerabilidades, revelando os riscos de próxima geração na cadeia de suprimentos de software e em aplicações

1 comentários

 
GN⁺ 2024-03-01
Comentários do Hacker News
  • Indo além do alerta geral de que é preciso ter cuidado com código vindo de repositórios públicos ou fontes externas e fazer verificação da árvore de dependências, fica a dúvida sobre que impacto haveria em LLMs e ferramentas de automação treinados com esse conteúdo se houver código malicioso em massa em repositórios públicos
    Parece possível que, quando ferramentas como o Copilot geram respostas longas de código, partes maliciosas acabem entrando por acaso
    Coisas como vulnerabilidades simples de injeção já são vistas com frequência

    • Mais do que backdoors entrarem por acaso na saída de LLMs, preocupa mais a possibilidade de agências de inteligência implantarem backdoors na saída de LLMs
      Talvez não agora, mas parece bem plausível dentro de alguns anos
    • LLMs provavelmente não só colam código vulnerável que estava nos dados de entrada, como também criam novas vulnerabilidades por conta própria
      IA não dá nenhuma garantia de precisão
    • Acabei de postar uma questão relacionada a LLMs sobre o sequestro do bot de conversão safetensors da Hugging Face: https://news.ycombinator.com/item?id=39549482
      Foi demonstrado que um atacante pode assumir o controle de um bot de serviço conectado ao espaço de conversão Hugging Face Safetensors, que é um serviço popular para converter modelos de machine learning inseguros no ecossistema em versões mais seguras
    • É um risco real, mas parecido com o risco de, ao aceitar sem revisão o PR de um colega, entrar código vulnerável copiado de algum lugar
      Para usar LLMs, é preciso investir mais esforço em revisão de código, e acho que esse compromisso vale a pena
    • O número de amostras detectadas nesta campanha é tão grande que o risco é mais realista do que parece
      Ainda assim, para virar um incidente real, há principalmente duas barreiras: o gerador recebe instruções internas para evitar esse tipo de código, e, pela natureza dos LLMs, é pouco provável que repita exatamente o endereço do atacante real
      Mesmo assim, vários vetores de ataque, como bind shell, negação de serviço e exfiltração local, ainda permanecem
  • O GitHub está fracassando de modo parecido com o fracasso da Usenet
    Qualquer um pode criar um repositório, e não há nada que diferencie repositórios oficiais de repositórios de spam
    Assim como a Amazon mirou ser “a loja de tudo” e acabou esbarrando em “90% de tudo é lixo”, tornando-se uma loja em que a maior parte é lixo, o GitHub precisa decidir se seu produto é “repositórios para todos” ou “código confiável”
    Por exemplo, no PG JDBC oficial não parece haver nenhum elemento que um spammer não consiga reproduzir; então como confiar que isto não é um repositório infectado: https://github.com/pgjdbc

    • Parece que o GitHub escolheu repositórios para todos já há 16 anos, quando a empresa começou
    • Se for uma biblioteca Java, normalmente ela é baixada do Maven Central, não do GitHub
      A Sonatype exige comprovação de propriedade do domínio reverso usado no groupId, que neste caso é org.postgresql
      O método está aqui: https://central.sonatype.org/faq/how-to-set-txt-record/
      Para mais tranquilidade, como todos os artefatos publicados no Maven Central são assinados, também é possível verificar a assinatura GPG, mas a desvantagem é que seria preciso obter a chave que o Postgres usa para assinatura por um caminho independente da Sonatype
      No caso do PG, uma busca rápida não encontrou a chave
    • Acho que não há uma noção adequada de quão pequeno é esse número
      O GitHub tem cerca de 500 milhões de repositórios, então isso na verdade é bem bom
    • Mais de 100 mil repositórios infectados não é bom, mas isso não significa que o GitHub fracassou
      Um desenvolvedor que usaria um repositório infectado encontraria muitos outros meios de criar um produto inseguro mesmo que tais repositórios não existissem no GitHub
    • Ao comprovar a propriedade do domínio, é possível receber um selo de verificação na página da organização, o que pode aumentar bastante a confiança
      A organização usada como exemplo simplesmente parece não ter feito isso
  • Problemas de cadeia de suprimentos são realmente uma dor de cabeça
    Não miro diretamente os releases do npm, mas estou criando releases no npm para monitorar, usando o socket.dev, um projeto de navegador web com virtualização leve chamado BrowserBox
    Mesmo esse projeto tem cerca de 800 dependências contando todas as dependências transitivas, embora use apenas 19 dependências de nível superior; ainda assim, no contexto da stack inteira, é relativamente leve
    Agora estou pensando em tirar snapshots de todas as 800 dependências no namespace @browserbox do npm, acompanhar as vulnerabilidades encontradas e aplicar patches
    Parece coisa de doido, mas é a situação atual; pelo menos assim dá para garantir diretamente, dentro do nível de segurança da empresa, as vulnerabilidades de cadeia de suprimentos do lado de Node/JS
    https://socket.dev
    https://github.com/BrowserBox/BrowserBox

    • Não sei quanto disso existe no npm, mas no crates.io e no cargo há ferramentas como cargo audit e cargo deny para verificar CVEs na árvore de dependências dentro do pipeline
      Como o arquivo de lock mantém o sha256 de toda a árvore, não é necessário espelhar para evitar alterações mesmo que o repositório seja hackeado
      Fixar em uma versão alguns meses atrás da mais recente parece um bom equilíbrio para evitar CVEs novas sem ficar preso a versões velhas demais e acabar tendo de fazer uma grande correção de uma vez
      O número de downloads parece uma métrica razoável quando comparado a dependências de nível superior com propósito parecido, mas é um julgamento subjetivo
      Austral usa tipos lineares para conceder permissões granulares às dependências
      Algo como: uma biblioteca gráfica não precisa de E/S de arquivos, e uma biblioteca de transporte de rede não precisa de acesso ao microfone
      É apenas uma mitigação, mas eu gostaria de ver isso em outras linguagens também
    • A expressão “apenas cerca de 800 dependências” dá um certo arrepio
      Depois de sair de .NET para Java uns 10 anos atrás, fiquei surpreso com o quanto aumentou o tempo gasto em inferno de dependências; hoje, tanto em projetos Java quanto Python, a quantidade de tempo dedicada a atualizações de vulnerabilidades e problemas de dependências é assustadora
      Acho que esse problema era menor em .NET porque a adoção de gerenciamento automático de pacotes foi relativamente tardia e o NuGet também era bastante novo; na época, muitos projetos ainda não o tinham adotado, então havia uma cultura forte de evitar árvores enormes de dependências transitivas
      Os problemas recentes da Boeing parecem parecidos
      Nas últimas décadas, ao transferir cada vez mais a produção para fornecedores externos e focar em otimização de custos, o gerenciamento da cadeia de suprimentos ficou cada vez mais difícil; em uma visão mais ampla, isso se parece com a cultura de cadeia de suprimentos da engenharia de software moderna
      Quando trabalhei em uma instituição financeira que proibiu gerenciadores de pacotes por causa da segurança da cadeia de suprimentos, o gerenciamento de dependências foi o menos incômodo e também foi onde houve menos problemas de qualidade
      Há vantagens em código que nunca muda a menos que você o altere explicitamente
      Implementávamos internamente muita coisa que outros usariam via pacotes, mas, como fazíamos apenas o necessário e aplicávamos padrões de código mais altos, era mais fácil entender, depurar e modificar
      O custo de escrever pela primeira vez é único e se amortiza bem, mas o custo recorrente de lidar com código que tenta fazer tudo para todos fica maior no longo prazo e normalmente se acumula
      “Simple Made Easy”, de Rich Hickey, mostrou bem esse fenômeno: simples e fácil são coisas diferentes, e opções simples podem parecer mais difíceis no começo, mas ficam mais fáceis no longo prazo quando os efeitos de segunda ordem se acumulam
  • Eu já tinha percebido isso por acaso ao ver repositórios parecidos
    Eu já não executava código de qualquer repositório aleatório, mas agora, mesmo confiando no repositório e no dono, abro uma VM em sandbox
    Parece que, hoje, como desenvolvedor, você precisa separar claramente pelo menos três ambientes: trabalho, hobby e uso pessoal

    • O simples fato de se dizer que desenvolvedores devem separar ambientes de trabalho, hobby e uso pessoal mostra que a complexidade da vida digital cresceu a ponto de fazer duvidar se ela é sustentável no longo prazo
    • A cada ano, Qubes parece uma escolha mais razoável
    • Eu também faço isso hoje, e não só por causa de software potencialmente malicioso
      Há projetos que, mesmo não sendo maliciosos, são mal projetados ou escritos de forma idiota
      Um programa que executei há pouco tempo adicionou 3 linhas ao meu ~/.bashrc antes mesmo de eu pedir qualquer coisa, e só percebi alguns dias depois
      Não consigo entender que tipo de desenvolvedor acha isso uma boa ideia; por isso, agora uso sandbox sempre que executo código externo
    • Isso soa como um bom motivo para usar Qubes OS, onde tudo roda em uma VM por padrão
      É meu OS do dia a dia
    • Parece básico não misturar ambientes de trabalho e pessoais
      Existem mesmo empregadores que permitem isso?
  • Fico curioso para saber quais ferramentas vocês usam no trabalho para evitar esse tipo de problema e se estão satisfeitos com a configuração atual
    Estou desenvolvendo um SDK com muitos downloads semanais em uma equipe bem pequena, e avaliamos soluções baseadas em snyk, aikido.dev, renovate etc., mas não está claro se elas ajudam nesse tipo de problema
    Como ainda somos uma equipe pequena, também é pesado lidar com ferramentas com muitos falsos positivos, como o snyk

    • Em vez de usar repositórios do GitHub diretamente, usamos pacotes públicos de repositórios comuns como NuGet, PyPI e npm, e colocamos o Repository e o Firewall da Sonatype como proxy entre nós e os repositórios de pacotes
      A Sonatype analisa todos os pacotes, adiciona vários metadados e define políticas que podem ser usadas no Firewall para filtrar o restante
      Só funciona para dependências públicas, mas, depois de alguns anos de uso, funciona muito bem
      Até agora não tivemos problemas com malware, pacotes com vulnerabilidades conhecidas não entram na base de código e recebemos alertas quando uma vulnerabilidade é encontrada em algo que estamos usando
    • No trabalho, usamos Semgrep Supply Chain e estamos bastante satisfeitos
      Ele separa as vulnerabilidades de cadeia de suprimentos encontradas em alcançáveis, não alcançáveis e indeterminadas, o que tornou a triagem muito mais fácil e reduziu bastante o tempo para avaliar novas vulnerabilidades
    • Parece que, nesta subthread, há muita confusão entre malware e vulnerabilidades
      Os fornecedores mencionados não detectam código malicioso; detectam apenas vulnerabilidades
      Mesmo que sejam bons em detectar vulnerabilidades, você ainda não fica protegido contra código malicioso inserido na base de código
    • Estamos criando uma ferramenta open source chamada Packj, que detecta pacotes PyPI/NPM/Ruby/PHP/Maven/Rust perigosos, como pacotes publicamente maliciosos, abandonados e de typosquatting
      Ela realiza análises estática, dinâmica e de metadados, e marca pacotes perigosos verificando mais de 40 atributos, como execução de shell, uso de chaves SSH, comunicação de rede e uso de decode+eval
      https://github.com/ossillate-inc/packj
    • Vale dar uma olhada no Trivy
      Até agora tem funcionado muito bem
      https://trivy.dev/
  • Fico me perguntando se a prática de baixar scripts de instalação de shell com curl e executá-los com sudo vai acabar em breve
    Algo como “para instalar nosso software, execute curl [https://somesite/install.sh](<https://somesite/install.sh>;)' | sudo sh” parece se encaixar muito bem com o código infectado mencionado no artigo

    • Como autor deste estudo, posso confirmar
      Nosso sistema lista cerca de 100 ocorrências por semana do padrão mencionado, e cerca de 3% delas são maliciosas
      Eu gostaria de ver essa prática acabar
    • Infelizmente, npm i tem as mesmas permissões
      Entre as ferramentas comuns atuais para baixar dependências, a única que conheço em que código hostil não é executado no momento da instalação ou do build é mais ou menos go get
      No mínimo, precisamos de ferramentas melhores para trabalhar em sandbox, para compartimentalizar a explosão
      A forma do ChromeOS de “uma máquina virtual poder abrir janelas Wayland no desktop principal” é elegante, mas, da última vez que vi, aquele código não era muito limpo nem reutilizável
    • Para exemplos como esse, é melhor usar example.com
      É um domínio reservado para esse fim: https://www.rfc-editor.org/rfc/rfc2606.html#section-3
    • Não é particularmente pior do que as alternativas realistas: “adicione o repositório da distribuição e confie nele”, “baixe o .deb/.rpm/instalador” ou, na pior das hipóteses, “confie em algo empacotado por terceiros, não pelo publicador”
  • No npm, é possível mitigar a execução de malware com --ignore-scripts
    https://blog.uirig.com/getting-rid-of-npm-scripts

    • Em vez disso, o código malicioso baixado pode acabar sendo executado em produção
      Com sorte, ele pode apresentar algum comportamento estranho no CI e ser pego
      A solução real é um sistema de reputação como https://github.com/crev-dev/cargo-crev, mas infelizmente quase não é usado
    • Do ponto de vista de segurança, deveria ser o padrão
      Também vale prestar atenção ao comentário de que um Makefile é necessário
  • Com a continuidade desses relatórios, venho melhorando aos poucos a segurança do ambiente de desenvolvimento nos últimos meses
    Uso dev containers do VSCode para desenvolvimento: https://code.visualstudio.com/docs/devcontainers/create-dev-...
    Depois de criar uma vez, é fácil de usar mesmo sem muito conhecimento de Docker, e é bom para subir apps web/de console, mas coisas como Flutter ou Electron foram difíceis
    Também me acostumei com o GitHub Codespaces para projetos pequenos: https://github.com/codespaces
    No passado, em uma entrevista, já fiz live coding para modificar um projeto Node simples; hoje em dia, em uma situação dessas, acho que certamente usaria contêineres ou Codespaces: https://www.welivesecurity.com/en/eset-research/lazarus-luri...
    Para boas práticas de npm, Node e Docker, leio regularmente as diretrizes da OWASP e aplico coisas como usar imagens Docker tão pequenas quanto possível e tags de imagem explícitas: https://cheatsheetseries.owasp.org/cheatsheets/NodeJS_Docker...
    Para pacotes npm/python, antes de instalar, verifico no socket.dev acesso a variáveis de ambiente, chamadas de rede, ataques à cadeia de suprimentos, mudanças recentes de propriedade do código etc.; e, como a OWASP recomenda, também é possível desativar globalmente scripts postinstall: https://cheatsheetseries.owasp.org/cheatsheets/NPM_Security_...

  • Houve, há menos de um ano, um caso de repositório com vírus cavalo de Troia: https://github.com/orgs/community/discussions/63603

    • O repositório afirmava ser um ladrão de senhas; se alguém baixou, descompactou e ele roubou informações pessoais e arquivos, não vejo qual é o problema
      Ele apenas funcionou exatamente como o repositório dizia
  • Só indicar que é um repositório oficial já poderia chamar alguma atenção

    • Mais tarde, talvez o GitHub comece a vender aquele check azul
      O que poderia dar errado /s
      Ainda assim, concordo que o GitHub deveria mostrar melhor qual repositório é o oficial de um projeto