A técnica Zenbleed
(lock.cmpxchg8b.com)- Zenbleed é uma vulnerabilidade que explora a recuperação incorreta de
vzerouppersob erro de predição na família AMD Zen 2, permitindo ler dados remanescentes no arquivo de registradores vetoriais do mesmo núcleo físico - Registrada como CVE-2023-20593, afeta a linha Zen 2, incluindo Ryzen 3000/4000/5000 with Radeon Graphics/7020 with Radeon Graphics, Ryzen PRO, Threadripper 3000 e EPYC “Rome”
- O ataque se concretiza quando XMM Register Merge Optimization, renomeação de registradores e um
vzerouppermal previsto ocorrem em uma janela de tempo estreita; até operações básicas comostrlen,memcpyestrcmppodem se tornar alvos de observação - Uma variante otimizada pode vazar cerca de 30 KB por segundo por núcleo, e o compartilhamento do arquivo de registradores no mesmo núcleo físico atravessa fronteiras de VM, sandbox, contêiner e processo
- Recomenda-se aplicar a atualização de microcódigo da AMD; temporariamente, é possível definir o chicken bit
DE_CFG[9], mas isso pode ter custo de desempenho, e desativar apenas o SMT não basta
Unidade de execução visada pelo Zenbleed
- CPUs x86-64 têm registradores vetoriais XMM de 128 bits, e CPUs modernas os expandem para YMM de 256 bits e ZMM de 512 bits
- Registradores vetoriais são usados não só em cálculos numéricos, mas também em funções da biblioteca padrão C do glibc como
strcmp,memcpyestrlen - O
strlenotimizado com AVX2 no glibc combina várias instruções vetoriais para encontrar a posição do primeiro byte nul em uma stringvpxor xmm0,xmm0,xmm0zera a parte inferior deymm0vpcmpeqb ymm1,ymm0,[rdi]compara os bytes da string com bytes zerovpmovmskb eax,ymm1move o resultado da comparação para um registrador geraltzcnt eax,eaxcalcula a posição do primeiro byte nul
vzeroupper e o arquivo de registradores
vzeroupperé uma instrução que zera os bits superiores dos registradores vetoriais- Ao misturar o uso de registradores
XMMeYMM, um registradorXMMpode ser promovido para a largura total, criando dependências nos bits superiores - O glibc usa
vzeroupperpara evitar stalls desnecessários, fazendo com que resultados posteriores não dependam dos bits superiores - A CPU não mantém cada registrador em uma posição física fixa; ela gerencia a alocação de registradores físicos com o Register File e a Register Allocation Table
- Ao zerar um registrador
XMM, a CPU pode não armazenar os bits reais e, em vez disso, definir uma flag z-bit na RAT- Essa flag pode ser aplicada de forma independente às partes superior e inferior de um registrador
YMM vzeroupperpode definir o z-bit e então liberar aquele recurso no arquivo de registradores
- Essa flag pode ser aplicada de forma independente às partes superior e inferior de um registrador
Vulnerabilidade na recuperação da execução especulativa
- CPUs modernas usam execução especulativa, então operações executadas em um desvio mal previsto precisam ser revertidas
- O problema é que, quando um
vzerouppermal previsto é executado e depois recuperado, reverter apenas o z-bit não restaura corretamente o estado do recurso do arquivo de registradores que já foi liberado - Com escalonamento preciso, é possível fazer alguns processadores se recuperarem incorretamente de um
vzerouppermal previsto - Essa técnica é a CVE-2023-20593 e afeta toda a família Zen 2
- AMD Ryzen 3000 Series Processors
- AMD Ryzen PRO 3000 Series Processors
- AMD Ryzen Threadripper 3000 Series Processors
- AMD Ryzen 4000 Series Processors with Radeon Graphics
- AMD Ryzen PRO 4000 Series Processors
- AMD Ryzen 5000 Series Processors with Radeon Graphics
- AMD Ryzen 7020 Series Processors with Radeon Graphics
- AMD EPYC “Rome” Processors
Condições do ataque e alcance do vazamento
- Para acionar o bug, XMM Register Merge Optimization, renomeação de registradores e um
vzerouppermal previsto precisam ocorrer em uma janela de tempo precisa - A sequência de instruções de exemplo usa a seguinte estrutura
vcvtsi2s{s,d}aciona a merge optimizationvmovdqaaciona a renomeação de registradores- Se o desvio condicional for taken, mas a CPU prever o caminho not-taken,
vzeroupperserá executado por erro de predição e o bug ocorrerá
- Como operações básicas como
strlen,memcpyestrcmptambém usam registradores vetoriais, elas podem se tornar alvos de observação em qualquer ponto do sistema - Como o arquivo de registradores é compartilhado no mesmo núcleo físico, outras VMs, sandboxes, contêineres e processos também entram no escopo do impacto
- Os dois hyperthreads compartilham o mesmo arquivo de registradores físicos
- Uma variante otimizada do ataque pode vazar cerca de 30 KB por segundo por núcleo, velocidade suficiente para monitorar chaves criptográficas e senhas de um usuário conectado
- O boletim técnico e o código relacionado foram publicados no repositório de pesquisa em segurança do Google
- O código de teste é fornecido para Linux, mas o bug não depende de um sistema operacional específico, então todos os sistemas operacionais são afetados
Como foi descoberto: fuzzing de CPU e Oracle Serialization
- A vulnerabilidade foi descoberta por fuzzing
- A indústria de CPUs também realiza validação pós-silício para encontrar falhas de hardware após a fabricação
- Diferentemente do fuzzing tradicional baseado em cobertura, CPUs não têm uma métrica que corresponda diretamente à cobertura de código
- Em vez disso, usam-se performance counters para fornecer ao fuzzer feedback sobre eventos arquiteturais interessantes
- Com isso, é possível explorar sequências de instruções difíceis de encontrar por acaso
- Foi possível descobrir automaticamente recursos como merge optimization
- O fuzzing de software normalmente procura crashes, mas em programas de CPU gerados aleatoriamente um crash pode, por si só, ser um comportamento correto
- Uma das abordagens existentes, reversi, gera uma operação inversa para cada instrução aleatória e verifica se o estado final difere do estado inicial
- Em arquiteturas CISC como x86, a geração de casos de teste fica mais complexa
- Outra abordagem usa um oracle para comparar os resultados da CPU em teste com outra CPU ou com um simulador
- Oracle Serialization combina as duas ideias
- Primeiro gera um programa aleatório e depois o converte automaticamente para uma forma serializada
- Adiciona elementos de serialização como store/load barrier, speculation fence e cache line flush
- O programa original e o programa serializado devem produzir a mesma saída, mesmo com características de desempenho diferentes
- Se o estado final não coincidir, pode haver um erro de execução microarquitetural, e essa divergência levou à descoberta do Zenbleed
Mitigação e limites de detecção
- A vulnerabilidade foi reportada à AMD em 15 de maio de 2023
- A AMD distribuiu uma atualização de microcódigo para os processadores afetados
- O fabricante da BIOS ou o fornecedor do sistema operacional pode já ter disponibilizado um patch com essa atualização incluída
- A mitigação recomendada é aplicar a atualização de microcódigo
- Quando não for possível aplicar a atualização, pode-se usar como paliativo de software a definição do chicken bit
DE_CFG[9]- Isso pode ter custo de desempenho
- No Linux, é possível defini-lo em todos os núcleos com
msr-tools - No FreeBSD, usa-se
cpucontrol(8) - Se você não souber como definir MSRs em outros sistemas operacionais, será necessário suporte do fornecedor
- Desativar apenas o SMT não é suficiente
- Não há técnicas confiáveis de detecção de ataque conhecidas
- Porque não são necessárias chamadas de sistema especiais nem privilégios
- Também não é possível detectar estaticamente o uso inadequado de
vzeroupper
1 comentários
Opiniões do Hacker News
Isso é realmente impressionante e serve como um caso clássico de que rodar em uma VM não significa estar seguro
Escape de VM sempre foi algo conhecido, mas desta vez é uma vulnerabilidade em larga escala, simples de explorar e com grande retorno mesmo sem escape
O fato de este bug ser corrigido por microcódigo não significa que não existam outros bugs parecidos. Muitos 0-days costumam ser conhecidos por black hats mercenários muito antes de se tornarem públicos
Vulnerabilidades de CPU descobertas nos últimos anos:
https://en.wikipedia.org/wiki/Meltdown_(security_vulnerability)
https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)
https://aepicleak.com/
https://en.wikipedia.org/wiki/Software_Guard_Extensions#SGAxe
https://en.wikipedia.org/wiki/Software_Guard_Extensions#LVI
https://en.wikipedia.org/wiki/Software_Guard_Extensions#Plundervolt
https://en.wikipedia.org/wiki/Software_Guard_Extensions/…
https://en.wikipedia.org/wiki/Software_Guard_Extensions#Enclave_attack
https://en.wikipedia.org/wiki/Software_Guard_Extensions/…
https://www.vusec.net/projects/crosstalk/
https://en.wikipedia.org/wiki/Hertzbleed
https://securityweek.com/amd-processors-expose-sensitive-data-new-squi…
Em vez de interpretar instruções com um grande
switch, ela executa instruções no CPU real e depende de algumas flags de hardware que garantem que dados ou instruções não se sobreponham. O CPU promete isso, mas na prática é difícil cumprir esse tipo de promessaNaqueles casos, o CPU fazia exatamente o que deveria fazer, mas surgiu uma forma de ataque totalmente nova baseada em timing; já o Zenbleed se parece mais com um bug tradicional em que dados que não deveriam estar ali permanecem em registradores
Muitas dessas vulnerabilidades parecem surgir de software e hardware não conversarem direito entre si. O lado do software parte de certas suposições sobre garantias de isolamento, e o lado do hardware não avisa adequadamente quando essas suposições podem surgir
Dá a sensação de que a predição de desvios é intrinsecamente complexa demais e por isso sempre ficará exposta a esse tipo de vulnerabilidade, ou então é tão diferente da forma intuitiva como entendemos caminhos de código e execução de instruções que fica difícil imaginar as condições de contorno antes que seja tarde demais
Será que a complexidade da arquitetura de CPU vai chegar a um ponto em que ficará difícil demais raciocinar sobre ela, a ponto de aceitarmos a perda de desempenho para mantê-la mais simples?
Apontei isso e recomendei air gap com hypervisors separados, mas sempre fui ignorado. No fim, o prejuízo deve ser deles
O README do arquivo tar do exploit contém mais detalhes e o cronograma de divulgação
2023-05-09Um componente do pipeline de validação de CPU gerou resultados anormais2023-05-12O problema foi isolado e reproduzido com sucesso; a investigação continuou2023-05-14O alcance e a gravidade do problema foram identificados2023-05-15Foi elaborado um breve relatório de status e compartilhado com o AMD PSIRT2023-05-17A AMD confirmou o relatório e reconheceu que era reproduzível2023-05-17O desenvolvimento de um PoC confiável foi concluído e compartilhado com a AMD2023-05-19Começaram a avisar os principais fornecedores de kernel e hipervisores2023-05-23Recebida da AMD uma atualização beta de microcódigo para Rome2023-05-24Confirmaram que a atualização corrigia o problema e avisaram a AMD2023-05-30A AMD informou que havia enviado um aviso de segurança aos parceiros2023-06-12Reunião com a AMD para discutir o status e os detalhes2023-07-20A AMD publicou o patch sem aviso prévio antes da data de embargo acordada2023-07-21Como a correção já estava pública, foi proposto avisar em particular as principais distribuições para prepararem atualizações de pacotes de firmware2023-07-24Divulgação públicaPublicou o patch antes do embargo acordado, e só depois surgiu o movimento de avisar em particular as principais distribuições de que precisavam preparar pacotes de firmware
amd-ucode 20230625.ee91452d-5do Arch Linux inclui a atualização de microcódigo que corrige esse problemahttps://archlinux.org/packages/core/any/amd-ucode/ foi atualizado pela última vez em 2023-07-25 11:48 UTC, e https://git.kernel.org/pub/scm/linux/kernel/git/firmware/lin... indica que a versão corrigida é de 2023-07-18
No início, achei que ainda usasse o firmware 20230625 por causa de
_tag=20230625no PKGBUILD e desource=("git+[https://git.kernel.org/pub/scm/linux/kernel/git/firmware/lin...](<https://git.kernel.org/pub/scm/…;)")Mas há dois commits cherry-pick no array
_backports, editados há 20 horas, eb250b32ab1d044953af2dc5e790819a7703b7ee6em https://gitlab.archlinux.org/archlinux/packaging/packages/li... é o mesmo commit do kernel.org linkado acima, então espero que o Arch mais recente não seja vulnerável ao ZenbleedIsso é realmente assustador. No meu equipamento Zen 2, um Ryzen 3600, executei o exploit como usuário sem privilégios e, ao copiar e colar uma string no editor de texto em segundo plano (Kate), fragmentos dessa string apareceram registrados na saída do zenbleed em poucos segundos
Felizmente, este exploit parece depender fortemente de uma rotina específica em assembly, então deve ser bem difícil explorá-lo a partir de JS ou WASM no navegador. Se não fosse assim, seria fácil vazar dados apenas deixando uma aba maliciosa aberta em segundo plano por algumas horas
Estou esperando o mantenedor do Fedora distribuir o novo microcódigo para que o kernel possa atualizá-lo durante o processo de boot
Ao mesmo tempo, espero que os patches de software no V8 e no SpiderMonkey cheguem antes e ofereçam mitigação adicional
Ainda assim, um exploit em JS também precisaria de uma forma de exfiltrar os dados, e parece que seria bem difícil esconder isso completamente
"No such file or directory"e error 127O fato de o OpenBSD ter adicionado carregamento de microcódigo AMD nos últimos 3 dias não parece coincidência
https://news.ycombinator.com/item?id=36838511
A afirmação de que a AMD lançou atualizações de microcódigo para os processadores afetados não parece muito precisa.
A AMD lançou atualizações de microcódigo[0] para a family 17h modelos
0x31e0xa0, e segundo a WikiChip[1] isso corresponde a Rome, Castle Peak e Mendocino.Até agora, não parece haver atualizações de microcódigo para Renoir, Grey Hawk, Lucienne, Matisse e Van Gogh. Felizmente, os kernels novos podem simplesmente definir o chicken bit para eles, e de fato fazem isso[2].
[0] https://git.kernel.org/pub/scm/linux/kernel/git/firmware/lin...
[1] https://en.wikichip.org/wiki/amd/cpuid#Family_23_.2817h.29
[2] https://github.com/torvalds/linux/commit/522b1d69219d8f08317...
good_revsestão aqui: https://github.com/torvalds/linux/commit/522b1d69219d8f08317...As revisões (
Patch) atualmente públicas podem ser vistas aqui, no git HEAD: https://git.kernel.org/pub/scm/linux/kernel/git/firmware/lin...No momento em que escrevo, apenas duas das cinco
good_revforam publicadas.Esse Celeron ficou famoso por 50% de overclock: https://ark.intel.com/content/www/us/en/ark/products/codenam...
Pelo trecho relevante, essa técnica é a CVE-2023-20593, funciona em todos os processadores classe Zen 2 e inclui pelo menos os seguintes produtos:
AMD Ryzen 3000 Series Processors
AMD Ryzen PRO 3000 Series Processors
AMD Ryzen Threadripper 3000 Series Processors
AMD Ryzen 4000 Series Processors with Radeon Graphics
AMD Ryzen PRO 4000 Series Processors
AMD Ryzen 5000 Series Processors with Radeon Graphics
AMD Ryzen 7020 Series Processors with Radeon Graphics
AMD EPYC “Rome” Processors
Será que a mesma técnica, ou alguma parecida, pode funcionar também nos núcleos Zen/Zen+ anteriores ou nos Zen 3 posteriores, mas isso ainda não foi demonstrado?
Meu
AMD Ryzen 9 5950x Desktop Processortambém parece ser Zen 3, então imagino que esteja tudo bem.Não executo cargas não confiáveis, mas a sorte favorece os preparados.
O site está caindo por causa do tráfego: https://web.archive.org/web/20230724143835/https://lock.cmpx...
Na maioria dos casos, o tráfego do HN mal chega a 100 pageviews por segundo.
https://www.amd.com/en/resources/product-security/bulletin/a...
Segundo o boletim de segurança da AMD, a atualização de firmware para CPUs não EPYC não sai antes do fim do ano. Até lá, os usuários precisam desativar o chicken bit e aceitar a perda de desempenho?
Tão impressionante quanto assustador. Rodei a amostra de 10 MB por 1 minuto e consegui “vazar” partes da minha senha do Bitwarden, da senha de login por ssh e fragmentos de credenciais bancárias, todos facilmente reconstruíveis.
O texto foi realmente muito bom. Gostei especialmente da parte que tratava de como é possível determinar se um programa gerado aleatoriamente foi executado corretamente
A abordagem óbvia é executá-lo em um oráculo, como outro processador ou um simulador, para ver se ele se comporta da mesma forma
Mas, para verificar efeitos microarquiteturais em janelas de tempo estreitas, também é possível escrever o mesmo programa inserindo vários stalls, fences, nops etc. Em código single-thread, isso não deveria afetar a saída, mas, dentro da CPU, acaba fazendo coisas bem diferentes do ponto de vista microarquitetural. Assim, a CPU pode se tornar seu próprio oráculo
Também gostei do chicken bit