2 pontos por GN⁺ 2023-07-25 | 1 comentários | Compartilhar no WhatsApp
  • Zenbleed é uma vulnerabilidade que explora a recuperação incorreta de vzeroupper sob 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 vzeroupper mal previsto ocorrem em uma janela de tempo estreita; até operações básicas como strlen, memcpy e strcmp podem 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, memcpy e strlen
  • O strlen otimizado com AVX2 no glibc combina várias instruções vetoriais para encontrar a posição do primeiro byte nul em uma string
    • vpxor xmm0,xmm0,xmm0 zera a parte inferior de ymm0
    • vpcmpeqb ymm1,ymm0,[rdi] compara os bytes da string com bytes zero
    • vpmovmskb eax,ymm1 move o resultado da comparação para um registrador geral
    • tzcnt eax,eax calcula 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 XMM e YMM, um registrador XMM pode ser promovido para a largura total, criando dependências nos bits superiores
  • O glibc usa vzeroupper para 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
    • vzeroupper pode definir o z-bit e então liberar aquele recurso no arquivo de registradores

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 vzeroupper mal 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 vzeroupper mal 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 vzeroupper mal 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 optimization
    • vmovdqa aciona a renomeação de registradores
    • Se o desvio condicional for taken, mas a CPU prever o caminho not-taken, vzeroupper será executado por erro de predição e o bug ocorrerá
  • Como operações básicas como strlen, memcpy e strcmp també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

 
GN⁺ 2023-07-25
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…

    • O problema é que VM já não é mais uma verdadeira máquina virtual
      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 promessa
    • A comparação com Meltdown/Spectre pode induzir um pouco ao erro
      Naqueles 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
    • Rodar código não confiável em sandbox, contêiner ou VM não era seguro, pelo menos desde Rowhammer
      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
    • No fim, parece que a maioria dessas coisas está relacionada a predição de desvios
      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?
    • Já vi algumas empresas misturando VMs expostas à internet/DMZ e VMs internas no mesmo hypervisor
      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-09 Um componente do pipeline de validação de CPU gerou resultados anormais
    2023-05-12 O problema foi isolado e reproduzido com sucesso; a investigação continuou
    2023-05-14 O alcance e a gravidade do problema foram identificados
    2023-05-15 Foi elaborado um breve relatório de status e compartilhado com o AMD PSIRT
    2023-05-17 A AMD confirmou o relatório e reconheceu que era reproduzível
    2023-05-17 O desenvolvimento de um PoC confiável foi concluído e compartilhado com a AMD
    2023-05-19 Começaram a avisar os principais fornecedores de kernel e hipervisores
    2023-05-23 Recebida da AMD uma atualização beta de microcódigo para Rome
    2023-05-24 Confirmaram que a atualização corrigia o problema e avisaram a AMD
    2023-05-30 A AMD informou que havia enviado um aviso de segurança aos parceiros
    2023-06-12 Reunião com a AMD para discutir o status e os detalhes
    2023-07-20 A AMD publicou o patch sem aviso prévio antes da data de embargo acordada
    2023-07-21 Como a correção já estava pública, foi proposto avisar em particular as principais distribuições para prepararem atualizações de pacotes de firmware
    2023-07-24 Divulgação pública

  • Isso é 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

    • Pelo menos uma pessoa aqui diz que também consegue reproduzir em JavaScript: https://news.ycombinator.com/item?id=36849767
    • Também testei no meu equipamento Zen 2, e o mesmo ataque funciona mesmo quando executado dentro do KVM
    • Se um método em JS for encontrado, parece haver potencial para aplicação bastante ampla
      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
    • Não sei como compilar o PoC. No Ubuntu aparece "No such file or directory" e error 127
  • O 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 0x31 e 0xa0, 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...

  • 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

    • Fico me perguntando se isso quer dizer “confirmado apenas no Zen 2” ou se o problema com certeza está restrito apenas a essa arquitetura.
      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 2700X parece ter escapado por pouco. Isso assumindo que a série 7020 é afetada e a série 7000 não.
    • Fico curioso sobre o PlayStation 5. O mesmo vale para o Xbox e aquele dispositivo da Valve.
    • Então Ryzen 5000 sem Radeon não é vulnerável? Esses processadores parecem ser Zen 3.
      Meu AMD Ryzen 9 5950x Desktop Processor també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.
    • Só para constar, Ryzen 3000 APU não é Zen 2.
  • O site está caindo por causa do tráfego: https://web.archive.org/web/20230724143835/https://lock.cmpx...

    • É só uma página HTML estática, então não entendo como um site estático consegue cair por tráfego em 2023.
      Na maioria dos casos, o tráfego do HN mal chega a 100 pageviews por segundo.
    • Link mais rápido: https://archive.is/QAwvQ
    • O original acaba carregando também. Pode variar conforme o ambiente.
  • 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?

    • A AMD enlouqueceu? Isso não é de gravidade média.
  • 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

    • Essa parte foi realmente fascinante, e gostei especialmente da diferença entre fuzzing de software e fuzzing de hardware
      Também gostei do chicken bit