Durante a Segunda Guerra Mundial, foi pedido a Abraham Wald que determinasse onde adicionar blindagem aos bombardeiros. O instinto dos militares era estudar os aviões que regressavam e reforçar os locais onde os impactos de balas se concentravam. Wald disse para fazer exatamente o oposto. Os aviões à sua frente já tinham sobrevivido a impactos nesses pontos. Era precisamente por isso que podiam ser estudados. Os aviões que sofreram impactos no motor ou na cabina nunca chegaram a regressar para ser estudados.
A engenharia de deteção tem o mesmo ponto cego, e é fácil de ignorar porque os aviões que sobrevivem parecem dar uma imagem completa se nunca perguntar o que não está à sua frente. Cada regra que escrevemos e cada padrão que rotulamos como "conhecido como malicioso" provém de pacotes de atacantes que conseguiram regressar até nós, o que significa que foram apanhados. Estamos a estudar os impactos de balas nos aviões que regressaram e a assumir que isso representa a imagem completa do que existe lá fora. Os criminologistas têm um nome para a versão com que lidam: o número oculto da criminalidade. Este é o espaço entre os incidentes que são detetados e os incidentes que realmente acontecem. Todas as estatísticas criminais baseiam-se nos criminosos que foram apanhados. Quem estuda o tema sabe disso e tem-no em conta.
A consequência para a criação de regras é desconfortável, mas importante. As regras ao nível de strings apenas conseguem apanhar atacantes que reutilizaram artefactos que já vimos anteriormente. Por definição, não conseguem apanhar um atac daor suficientemente sofisticado para nunca ter aparecido nos nossos dados de rastreio, da mesma forma que estudar aviões que regressaram nunca lhe mostrará onde foram atingidos os aviões que não regressaram. As regras ao nível comportamental são a nossa única verdadeira hipótese contra o desconhecido. O atacante ainda tem de exfiltrar os dados, ainda tem de executar o código, ainda tem de contactar o servidor de comando e controlo. O que fazem é limitado. Como o chamam, como o obscurecem e para onde o enviam, já não é.
Mas a identificação de comportamentos só ajuda se soubermos qual deve ser o aspeto do comportamento normal em primeiro lugar. Wald conseguiu apontar os aviões em falta porque já sabia qual era o aspeto de um avião inteiro e sem danos. Foi isso que lhe permitiu mapear cada impacto de bala em cada avião que regressava em relação a uma forma esperada completa: asas, fuselagem, cauda, motor, cabina, tudo. Uma vez obtido esse mapa completo, o que se destacava não era onde estava o dano. Era onde ele não estava.
A engenharia de deteção não obtém isto de forma gratuita. Se não tivermos uma imagem clara e completa do que é o comportamento normal de um pacote, uma chamada de rede inesperada ou o lançamento de um processo desconhecido não se registam como uma falha em nada. Apenas parecem mais ruído num sistema que não está mapeado.
O verdadeiro custo de um conjunto de dados de comportamento incompleto vai além de faltar uma regra ou duas. É perdermos a capacidade de reconhecer sequer a forma do que está em falta. Um atacante que nunca aparece nas nossas deteções baseadas em strings ainda tem de agir, e essa ação só é visível como anómala se tivermos definido a linha de base de onde se está a desviar. Sem essa linha de base, os pacotes invisíveis continuam invisíveis por uma segunda razão, para além da primeira. Não só evitaram deixar uma assinatura, como também estão a operar no espaço que nunca nos preocupámos em descrever, pelo que nada neles parece errado, a menos que analisemos as capacidades e os comportamentos dos pacotes.
Regras de strings baratas e de IOC são uma utilização racional do esforço. As estratégias utilizadas na esmagadora maioria dos pacotes maliciosos têm baixa sofisticação e são reutilizadas, com a mesma payload copiada ao longo de toda uma vaga de pacotes. Uma regra de string descartável apanha essa vaga inteira com quase nenhum custo, expira no momento em que o atacante altera o método e é reescrita com o mesmo baixo custo. O facto de as regras de strings baratas "morrerem jovens" significa que o escalão económico está a fazer exatamente o trabalho para o qual foi criado. Exigir uma linha de base comportamental dispendiosa para ameaças que uma regra de strings de cinco minutos já bloqueia seria uma utilização ineficiente do tempo.
A resposta é um portfólio de regras em toda a pirâmide. As regras baratas de escalão inferior lidam com o elevado volume. As regras dispendiosas de escalão superior são os únicos recursos que temos para alcançar os poucos sofisticados que se escondem no número oculto. Escalões diferentes, trabalhos diferentes; e a regra a que recorre depende inteiramente de qual é o atacante que está a tentar apanhar. É exatamente isto que a pirâmide adaptada seguinte apresenta.
Uma pirâmide adaptada
A pirâmide da dor de David Bianco [1] dá-nos uma forma de pensar sobre isto em camadas, em vez de tratar a deteção como uma categoria única e plana, adaptada aqui para o contexto da supply-chain de pacotes. Podemos classificar os tipos de indicadores consoante o custo que representam para um atacante os alterar, desde trivial até quase impossível. Isto varia desde ocorrências fortuitas, como valores de hash, até comportamentos deliberados e evidentes, como técnicas e estratégias.
Todos os níveis, exceto o topo, representam algo escolhido pelo atacante. Um domínio, um esquema de codificação, até mesmo uma ferramenta, tudo isto é uma decisão, e as decisões são refeitas no momento em que deixam de funcionar para o atacante. É isso que torna o nível mais alto da pirâmide o local ideal para criar regras duradouras, sendo também exatamente o sítio mais difícil de escrever uma, uma vez que as deteções ao nível da técnica e da estratégia necessitam de uma linha de base real por trás para funcionarem devidamente.
O que levanta a questão óbvia de saber de onde vem essa linha de base, pois a pirâmide não no-la faculta. Classificar os indicadores pelo custo que têm para mudar indica-nos onde residem as regras duradouras, e não como detetar um desvio em primeiro lugar. A forma mais prática de construir essa imagem é parar de procurar uma linha de base universal (que não existe) e passar a mapear o comportamento normal por tipo de pacote. Uma ferramenta de build, um utilitário de linha de comandos, um framework web e um pequeno utilitário de funções puras são tipos diferentes de software com capacidades distintas.
Uma ferramenta de build que gera processos filho e interage com o sistema de ficheiros durante a instalação está a comportar-se conforme esperado, enquanto um helper de formatação de strings que faça o mesmo não o está. As capacidades e ações do pacote determinam o comportamento aceitável, e as mesmas categorias de pacotes tendem a comportar-se de forma semelhante em npm, PyPI e NuGet, pelo que o perfil é suficientemente estável para ser reutilizado. Se completarmos esse mapa o suficiente, uma ação desconhecida deixa de ser interpretada como ruído e passa a ser vista como uma falha na forma esperada, que é precisamente o objetivo principal. É um trabalho considerável, e o mapa será sempre parcial, mas é esse o esforço que torna o topo da pirâmide alcançável.
Mapear a forma
Cada pacote que a Aikido Security ingere é analisado estaticamente e executado numa sandbox que regista o que efetivamente fez. Essa parte é comum. O que mudou é que agora um indicador transporta estrutura para além do facto de ter sido acionado. Cada um descreve o que o código correspondente é capaz de fazer e que tipo de evidência representa, permitindo ponderar um sinal que, isolado, significaria pouco, em comparação com os restantes à sua volta.
Isto permite que uma regra de deteção descreva uma forma e não uma string. Código que é executado no momento da instalação, à procura de credenciais a que não tem razão para aceder, a enviar algo para o exterior, num pacote cuja função declarada não explica nada disso. Não existe nenhum domínio numa regra assim, nem hash, nem nome de pacote. Nada que um atacante possa alterar.
A 4 de agosto de 2026, sinalizámos uma versão recentemente publicada do Keyv, que se apresentava como o mesmo utilitário de chave-valor popular e fiável, transferido 600 milhões de vezes a partir do NPM. No entanto, desta vez, durante a instalação, executou um ficheiro JavaScript fortemente ofuscado, que depois transferiu o Bun (um executador de JavaScript alternativo em vez do Node.js) e, por fim, executou outro ficheiro JavaScript ofuscado. Essas ferramentas e técnicas comportamentais foram suficientes para o nosso sistema detetá-lo. Se estivéssemos apenas a utilizar indicadores com nome, teríamos deixado escapar este pacote. Mas como procuramos o inesperado, conseguimos apanhar estes pacotes que, de outra forma, cairiam nesse espaço obscuro.
O nosso sistema concluiu corretamente o seguinte, embora não conseguisse ver toda a imagem devido à forte ofuscação: "A combinação de execução oculta no momento da instalação, obtenção remota de binários, preparação de payload e lançamento é suficiente para um veredito de malware de alta confiança, mesmo que o comportamento final do payload e qualquer objetivo de roubo de dados não tenham sido totalmente descodificados".
Atualmente, e tem sido pelo menos, difícil descodificar e compreender malware ofuscado, especialmente do ponto de vista da análise estática. Afinal, é por isso que os atacantes o colocam lá. O que podemos provar, em contrapartida, é que o comportamento dos pacotes maliciosos é suficiente para encontrarmos os números ocultos.
Ainda existe algum pequeno número oculto. Wald também nunca viu os aviões abatidos. O que lhe permitiu apurar onde tinham sido atinjáveis foi conhecer suficientemente bem a forma de um avião inteiro para notar onde o padrão se quebrava. A nossa versão dessa forma é uma linha de base do aspeto que o comportamento ordinário de um pacote tem, mantida atualizada em vez de assumida, e cada pacote que triamos acrescenta-se a ela. Os atacantes que ainda não apanhámos continuam condicionados pelo que o código tem de fazer para roubar algo. Cada uma dessas restrições é uma falha cuja localização já conhecemos num avião que não regressou.
Veja o que estamos a apanhar em Aikido Intel. Detetamos malware em minutos. Ligue o seu repositório à Aikido para analisar continuamente as dependências da sua aplicação à procura de pacotes maliciosos.
Referências
[1] Bianco, D. J. (2013). The Pyramid of Pain. Enterprise Detection and Response. http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html (revisto a 17 de janeiro de 2014, com a adição do nível de valores de hash).