GoFetch: como um recurso de velocidade dos chips M1, M2 e M3 da Apple abriu uma brecha que nenhum patch resolve de verdade

Em dezembro de 2023, um grupo de pesquisadores de sete universidades — Illinois Urbana-Champaign, Texas em Austin, Georgia Tech, Berkeley, Universidade de Washington e Carnegie Mellon — enviou à Apple um relatório de vulnerabilidade com um nome que parece brincadeira: GoFetch. Não era. O relatório descrevia como um mecanismo de otimização presente nos chips M1, M2 e M3 podia ser usado para extrair, na prática, chaves criptográficas secretas de programas rodando no mesmo computador — mesmo quando esses programas foram escritos seguindo a técnica considerada padrão-ouro contra esse tipo de ataque, o chamado código “de tempo constante”.

A pesquisa foi publicada e apresentada formalmente no USENIX Security 2024, um dos principais eventos acadêmicos de segurança do mundo, depois de passar por um período de divulgação responsável junto à Apple. O que torna o caso incomum não é só a gravidade — é o fato de que a causa-raiz está soldada no silício. Diferente de uma falha de sistema operacional ou de biblioteca, que se resolve baixando uma atualização, o problema do GoFetch nasce de uma decisão de arquitetura de hardware, e por isso resiste a soluções simples.

Este texto não é sobre pânico. É sobre entender, com precisão, o que de fato acontece dentro do chip: o que é um prefetcher, por que ele existe, o que muda quando ele passa a “olhar” para o conteúdo da memória, e por que isso é capaz de furar uma defesa que, até então, era tratada como confiável. Também vale adiantar o que este ataque exige na prática — porque a resposta não é “qualquer site pode roubar sua chave PIX”.

O que é um prefetcher, e por que a Apple construiu um mais esperto

Todo processador moderno passa boa parte do tempo esperando. A memória RAM é muito mais lenta que o núcleo de processamento, então, sempre que o chip precisa buscar um dado que não está nas memórias cache (as camadas de memória ultrarrápida mais próximas do núcleo), ele paga um pedágio de dezenas ou centenas de ciclos de espera. Para reduzir esse custo, os fabricantes de CPU embutem um componente chamado prefetcher: um circuito que tenta adivinhar quais endereços de memória o programa vai precisar em seguida e já busca esses dados com antecedência, antes mesmo de serem pedidos.

Os prefetchers “tradicionais” fazem essa previsão observando padrões de acesso — por exemplo, se o programa acabou de ler os endereços 100, 104 e 108, é razoável prever que o próximo será 112, e buscá-lo adiantado. Isso não olha para o conteúdo dos dados armazenados nesses endereços, apenas para a sequência de endereços já acessados. É uma otimização puramente estrutural, e por isso considerada segura do ponto de vista de vazamento de informação.

Só que a partir do M1, a Apple passou a usar também um tipo mais agressivo de prefetcher, batizado pelos pesquisadores de “prefetcher dependente de dados de memória” (data memory-dependent prefetcher, ou DMP). Diferente do modelo tradicional, o DMP examina o conteúdo dos valores que passam pelo cache e tenta identificar quais deles “parecem” um ponteiro — ou seja, um valor que se parece com um endereço de memória válido. Quando encontra um candidato, ele especulativamente busca antecipadamente o dado que estaria naquele endereço, apostando que o programa vai usá-lo em breve.

Quando otimização vira canal de vazamento

O detalhe crítico é este: para decidir se vai ou não prefetchar algo, o DMP precisa primeiro avaliar o valor armazenado na memória. E é exatamente essa avaliação que cria um problema, porque o valor em memória, dentro de uma implementação criptográfica, pode ser — e frequentemente é — um dado intermediário derivado da chave secreta que está sendo processada.

Segundo a descrição do próprio site oficial do paper, o DMP “ativa (e tenta desreferenciar) dados carregados da memória que ‘parecem’ um ponteiro”. Isso quer dizer que o comportamento do prefetcher — se ele dispara uma busca antecipada ou não, e para qual endereço — passa a depender do conteúdo dos dados, não apenas da sequência de endereços acessados. E um comportamento que depende do conteúdo de um dado secreto é, por definição, um canal lateral: um jeito indireto de vazar informação sobre esse segredo através de um efeito colateral observável, neste caso o tempo de execução e a ocupação do cache.

Um atacante que consiga rodar código no mesmo chip não precisa “ler” a chave diretamente. Basta medir, repetidamente, quanto tempo certas operações de memória levam — uma técnica de medição por canal lateral de cache já bem estabelecida na literatura de segurança — e observar se o padrão de tempo indica que o DMP disparou uma busca antecipada ou não. Esse sinal, repetido milhares de vezes ao longo da execução de um algoritmo criptográfico, é suficiente para reconstruir, bit a bit, valores que deveriam permanecer completamente secretos.

Por que isso derruba uma defesa considerada confiável

A técnica padrão que a criptografia moderna usa contra ataques de canal lateral de tempo se chama “tempo constante” (constant-time). A ideia é simples de enunciar: o código deve ser escrito de forma que o tempo de execução — e qualquer outro efeito observável, como quais endereços de memória são tocados — seja exatamente o mesmo, independentemente do valor da chave secreta sendo usada. Se um atacante não consegue observar nenhuma diferença de comportamento entre “processar a chave X” e “processar a chave Y”, ele não tem como usar tempo de execução para inferir nada sobre X ou Y.

O problema é que código de tempo constante garante apenas que a sequência de instruções executadas e os endereços de memória acessados pelo programa não dependem do segredo. Ele não tem como controlar o que um componente de hardware decide fazer por conta própria ao observar o conteúdo desses dados. O DMP opera numa camada abaixo do que o programador consegue enxergar ou controlar a partir do código-fonte: mesmo que o fluxo do programa seja idêntico para qualquer chave, o prefetcher pode reagir de forma diferente dependendo se o valor manipulado nesse instante “parece” ou não um ponteiro válido — e essa reação diferente é visível de fora, via tempo.

Em outras palavras: o GoFetch não encontra um bug em uma implementação criptográfica malfeita. Ele mostra que a própria premissa por trás do tempo constante — de que o programador consegue controlar todos os efeitos colaterais observáveis do seu código — deixou de valer quando o hardware embaixo do código passou a tomar decisões especulativas baseadas em dados. É por isso que os pesquisadores conseguiram quebrar implementações que já eram consideradas robustas e escritas seguindo as melhores práticas, incluindo bibliotecas amplamente auditadas.

O que foi demonstrado, chip a chip

O time por trás do GoFetch não ficou na teoria: construiu ataques de ponta a ponta contra implementações criptográficas reais. De acordo com o repositório oficial da pesquisa no GitHub e o site do projeto, os alvos demonstrados incluíram a troca de chaves Diffie-Hellman do OpenSSL, a decodificação RSA da biblioteca padrão do Go, e dois algoritmos de criptografia pós-quântica que estavam entre os finalistas do processo de padronização do NIST: CRYSTALS-Kyber (hoje padronizado como ML-KEM) e CRYSTALS-Dilithium (ML-DSA). O fato de algoritmos pensados para resistir a computadores quânticos também caírem para esse ataque de canal lateral mostra que o problema está num nível anterior ao da matemática do algoritmo — está em como qualquer implementação roda sobre esse hardware específico.

Nem todos os chips se comportam exatamente da mesma forma. No M1, os pesquisadores demonstraram ataques completos, de ponta a ponta. No M2, encontraram comportamento de DMP igualmente explorável e trataram o chip como vulnerável pelo mesmo mecanismo. Já no M3, a Apple incluiu um novo bit de controle chamado DIT (Data Independent Timing) que, segundo o site oficial do projeto, quando ativado, efetivamente desliga o DMP nesse chip — algo que não acontece da mesma forma nos modelos anteriores. Curiosamente, um bit de configuração de hardware separado (identificado por Hector Martin, pesquisador conhecido pelo projeto Asahi Linux) também permite desligar o DMP em M1 e M2, mas seu uso depende de suporte do sistema operacional que o macOS, até onde a pesquisa documenta, não expõe.

A divulgação seguiu o processo responsável padrão da área: os pesquisadores reportaram a falha à Apple em 5 de dezembro de 2023 e tornaram a pesquisa pública em março de 2024, cerca de 107 dias depois — tempo considerado razoável para o fabricante avaliar o problema antes da exposição pública. O trabalho completo foi então formalmente apresentado no USENIX Security Symposium de 2024 e, posteriormente, recebeu um Pwnie Award, prêmio informal mas respeitado da comunidade de segurança ofensiva para pesquisas de destaque no ano.

Por que não existe um “patch” simples — e o que a Apple fez até agora

Vale ser direto sobre o que este ataque exige na prática, porque isso muda completamente o nível de risco para a maioria das pessoas: o GoFetch não é um ataque remoto. Segundo reportagem do TechTarget, trata-se de um ataque de canal lateral local — o atacante precisa conseguir executar seu próprio código no mesmo Mac da vítima, sem privilégios elevados, mas rodando ali, para então medir o comportamento do cache enquanto o processo-alvo realiza operações criptográficas. Não é algo que um site malicioso consiga fazer sozinho a partir do navegador, nem uma técnica de invasão remota de um servidor. É por isso, inclusive, que o próprio projeto OpenSSL classifica ataques de canal lateral local como fora do seu modelo de ameaça oficial — não porque o problema seja irrelevante, mas porque a defesa contra “código arbitrário já rodando na sua máquina” pertence a outra camada de segurança, normalmente ao sistema operacional e às políticas de execução de aplicativos.

Isso não torna o problema trivial — cenários como uma extensão de navegador maliciosa, um aplicativo desonesto distribuído fora da App Store, ou uma máquina compartilhada com múltiplos usuários continuam plausíveis. Mas explica por que a Apple não tratou o caso com o mesmo alarme que trataria uma falha explorável remotamente.

Quanto a corrigir o problema: como o comportamento problemático está no circuito do prefetcher, não existe atualização de software capaz de “consertar” o DMP sem contornar seu funcionamento. As opções mapeadas pelos próprios pesquisadores, segundo cobertura da Macworld, são todas trade-offs caros: desligar o DMP inteiramente (o que, nos chips onde é possível, tem penalidade de desempenho relevante); mover código criptográfico para rodar nos núcleos de eficiência, que não têm DMP, sacrificando velocidade; ou reescrever cada implementação criptográfica com técnicas de “blindagem” (blinding) que mascaram os dados intermediários para que nunca pareçam ponteiros — o que exige retrabalho específico em cada biblioteca e também custa desempenho. A própria Apple, segundo a mesma reportagem, chegou a recomendar o uso do bit DIT para rotinas criptográficas sensíveis, mas essa configuração só desativa efetivamente o DMP no M3 — nos chips M1 e M2, seu efeito é mais limitado. Até o fechamento desta apuração, não há registro de um patch da Apple que elimine o problema nos chips M1 e M2 da forma como ele foi demonstrado pelos pesquisadores; a resposta pública da empresa se limitou a agradecer a pesquisa e apontar documentação existente sobre programação em tempo constante.


Fontes citadas neste artigo:

Deixe um comentário