Ataques à cadeia de suprimentos e builds determinísticos

·7 min de leitura·Por SSP Editorial Team
Ilustração de capa com ícones de carteira, chave, escudo e chip ao lado do título Ataques à cadeia de suprimentos e builds determinísticos

A maioria dos conselhos de segurança para usuários cripto foca nas superfícies que você consegue ver: sua frase semente, os links que você toca, os sites em que você faz login. Isso importa. Mas há um risco mais silencioso embaixo de tudo isso — o próprio software e tudo aquilo com que ele foi construído. Uma carteira pode ser escrita com perfeição e ainda assim distribuir um backdoor, porque aplicações modernas são montadas a partir de centenas de blocos de terceiros e de um pipeline de build que transforma o código-fonte no binário que você instala. Comprometa qualquer elo dessa cadeia e você compromete todos os usuários adiante.

Isso é a cadeia de suprimentos de software, e os atacantes aprenderam que ela é um dos alvos de maior alavancagem em cripto. Este artigo explica o que é de fato um ataque à cadeia de suprimentos, por que carteiras são alvos tão atraentes, as defesas que se sustentam na prática e o que os builds determinísticos trazem para você, incluindo como o SSP aplica tudo isso.

O que é um ataque à cadeia de suprimentos

Um ataque à cadeia de suprimentos não invade a aplicação diretamente. Em vez disso, compromete algo em que a aplicação confia: uma dependência que ela puxa, a conta de um mantenedor ou o pipeline de build que monta o artefato final. O código malicioso entra por uma atualização legítima, assinada e entregue pelos canais normais, então parece exatamente o software que você pretendia instalar.

Essa indireção é justamente o objetivo. Atacar uma biblioteca muito usada — ou um servidor de build — pode alcançar milhares de projetos derivados e milhões de usuários de uma só vez. Para uma carteira cripto a recompensa é direta: o código que roda dentro da sua carteira já tem acesso ao momento que importa, quando uma transação é assinada e os endereços são exibidos. Uma única dependência adulterada pode trocar um endereço de destino ou exfiltrar material de chaves sem nunca te tocar por phishing ou por uma higiene da frase semente fraca. É por isso que essa classe de ataque merece um lugar no seu modelo mental.

Dois casos que batem perto de casa

Dois incidentes reais mostram como isso acontece — um mirado diretamente em cripto, outro que quase atingiu a internet inteira.

event-stream e a carteira Copay

Em 2018, um popular pacote npm chamado event-stream foi repassado a um novo mantenedor voluntário que se ofereceu para ajudar. Foi uma transferência rotineira e de aparência bem-intencionada, do tipo que acontece o tempo todo no código aberto. O novo mantenedor então adicionou uma nova dependência, flatmap-stream, que continha código malicioso ofuscado.

A carga útil era incomumente direcionada. Em vez de disparar para todos, ela se ativava apenas dentro de um projeto derivado específico: a carteira Bitcoin Copay. Ali foi feita para roubar material da semente e fundos dos usuários daquela aplicação. A maioria dos desenvolvedores que puxaram event-stream nunca foi afetada — o código sabia exatamente qual vítima procurava.

É o lembrete canônico de que "só instalei uma pequena biblioteca" nunca é a história completa. Você instalou também tudo aquilo em que essa biblioteca confia.

O backdoor do XZ Utils

O incidente do XZ Utils de 2024 (CVE-2024-3094) foi ainda mais paciente. XZ Utils é uma biblioteca de compressão presente discretamente na maioria dos sistemas Linux. Ao longo de anos, um atacante foi construindo confiança como colaborador prestativo, assumiu aos poucos responsabilidades de manutenção e então inseriu um backdoor projetado para interferir no OpenSSH — o software que protege logins remotos em servidores no mundo todo.

Foi descoberto quase por acaso, por um engenheiro que notou um atraso de uma fração de segundo. Se tivesse sido distribuído amplamente, poderia ter entregado acesso remoto a incontáveis máquinas.

A lição para cripto é dura: o ataque não explorou um bug engenhoso, explorou o próprio modelo de confiança do código aberto, jogando um jogo de engenharia social de vários anos para se tornar a pessoa de quem todos dependiam.

As defesas que realmente funcionam

Nenhum controle isolado detém ataques à cadeia de suprimentos. O que funciona é uma pilha deles, cada um estreitando as opções do atacante:

  • Dependências fixadas e lockfiles. Fixar versões exatas e versionar um lockfile significa que um build não pode puxar em silêncio uma versão mais nova e adulterada. As atualizações se tornam eventos deliberados e revisáveis, em vez de automáticos.
  • Dependências mínimas. Cada pacote que você adiciona é uma parte em que você confia. Menos dependências significam uma superfície de ataque menor e menos mantenedores que poderiam ser comprometidos.
  • Sandbox de dependências. Ferramentas como o LavaMoat limitam o que cada pacote pode fazer em tempo de execução, de modo que uma dependência comprometida não consiga alcançar livremente a rede ou APIs sensíveis.
  • Assinatura de código. Versões assinadas permitem aos usuários verificar que um binário veio do publicador real e não foi alterado em trânsito.
  • Auditorias de terceiros. Empresas de segurança independentes revisam o código e as dependências com olhar adversário, pegando o que equipes internas normalizam.
  • Builds reproduzíveis e determinísticos. A defesa estrutural mais forte, e a que vale a pena entender em detalhe.

Builds determinísticos, explicados

Normalmente, compilar o mesmo código-fonte duas vezes pode produzir dois binários ligeiramente diferentes — vazam carimbos de tempo, ordenação de arquivos e detalhes da máquina de build. Essa variabilidade é um problema, porque significa que você não consegue distinguir uma diferença benigna de uma maliciosa.

Um build determinístico (ou reproduzível) elimina essa variabilidade. Dado o mesmo código-fonte, qualquer pessoa, em qualquer lugar, em qualquer máquina, produz um artefato idêntico byte a byte. A implicação é poderosa: pessoas independentes podem recompilar a carteira a partir do código-fonte público e confirmar que o binário que você baixou corresponde, bit a bit, ao que o código-fonte produz. Se um atacante adulterou o pipeline de build ou inseriu algo depois, os hashes não vão bater e a adulteração fica visível na hora.

Isso inverte o modelo de confiança. Você não precisa mais acreditar na palavra do publicador; a verificação se torna algo que toda a comunidade pode realizar e cruzar. O projeto Reproducible Builds documenta essa prática em todo o ecossistema, e frameworks como o SLSA definem níveis de garantia de integridade de build que você pode exigir de um projeto.

Como o SSP aplica isso

O SSP trata o pipeline de build como parte do seu modelo de ameaças, não como um detalhe posterior. A carteira é distribuída com um build determinístico baseado em Dockerfile: o mesmo ambiente definido por Docker produz o mesmo artefato toda vez, então uma versão publicada pode ser recompilada a partir do código-fonte público e comparada, bit a bit, com o que você baixou. O SSP também passou por revisões de segurança independentes da Halborn, cujas auditorias examinam tanto o código quanto as dependências em que ele se apoia.

Há mais uma camada, específica de como o SSP é construído, e aqui ela importa. O SSP é uma carteira multisig 2 de 2: cada transação exige uma aprovação independente de uma segunda chave, a SSP Key, em um dispositivo separado. Seja preciso sobre o que isso faz e o que não faz. Builds determinísticos e auditorias reduzem a chance de um build adulterado chegar a ser distribuído; eles são a linha de frente. Mas mesmo no pior caso — um build que de algum modo passou — a segunda chave é uma superfície de aprovação separada que ainda precisa assinar cada transação.

Não é um escudo mágico, e não torna aceitável um build comprometido. Significa apenas que um único componente adulterado em um dispositivo não move seus fundos por si só. Defesa em profundidade é a ideia.

O que você mesmo pode verificar

Você não precisa ser engenheiro de segurança para se beneficiar de tudo isso. Alguns hábitos rendem muito:

  • Baixe apenas de fontes oficiais. Pegue a carteira no site oficial ou na ficha da loja, nunca de um link em uma mensagem ou em um anúncio de busca. É a mesma disciplina coberta na higiene de extensões de navegador.
  • Prefira projetos que publicam builds determinísticos e auditorias. Um projeto que deixa a comunidade verificar suas versões — e paga por revisão independente — está te dizendo algo sobre como ele pensa.
  • Verifique assinaturas e hashes quando forem oferecidos. Se uma versão traz uma assinatura ou checksum, gaste o minuto para conferir. Builds reproduzíveis só protegem você se alguém de fato fizer a comparação.
  • Mantenha sua opsec geral firme. As defesas da cadeia de suprimentos ficam dentro de um quadro maior; revise sua checklist de opsec com regularidade para que nenhuma camada carregue todo o peso.

Nada disso exige confiar em uma única parte. Essa é exatamente a propriedade que você quer de um software de autocustódia.

Continue avançando

Uma carteira é tão confiável quanto a cadeia que a construiu. A boa notícia é que este é um dos poucos problemas de segurança com uma resposta limpa e estrutural: builds determinísticos mais auditorias independentes transformam o "confie em nós" em "verifique você mesmo".

Continue construindo suas defesas com consciência de phishing, boas práticas da frase semente, higiene de extensões de navegador e uma checklist de opsec periódica. Cada uma fecha uma porta; juntas, elas são a cara real da segurança em autocustódia.

Compartilhar este artigo

Artigos relacionados