2 puntos por GN⁺ 2023-07-25 | 1 comentarios | Compartir por WhatsApp
  • Zenbleed es una vulnerabilidad que aprovecha la recuperación incorrecta de vzeroupper mal predicho en la familia AMD Zen 2 para poder leer datos residuales en el archivo de registros vectoriales del mismo núcleo físico
  • Está registrada como CVE-2023-20593 y afecta a la familia de productos Zen 2, incluidos Ryzen 3000/4000/5000 with Radeon Graphics/7020 with Radeon Graphics, Ryzen PRO, Threadripper 3000 y EPYC “Rome”
  • El ataque funciona cuando XMM Register Merge Optimization, el renombrado de registros y un vzeroupper mal predicho ocurren en una ventana de tiempo estrecha; incluso operaciones básicas como strlen, memcpy y strcmp pueden quedar expuestas a observación
  • Una variante optimizada puede filtrar alrededor de 30 KB por segundo por núcleo, y el hecho de que se comparta el archivo de registros del mismo núcleo físico genera el problema a través de límites de VM, sandbox, contenedor y proceso
  • Se recomienda aplicar la actualización de microcódigo de AMD; como medida temporal se puede configurar el chicken bit DE_CFG[9], aunque puede tener costo de rendimiento, y desactivar SMT por sí solo no es suficiente

La unidad de ejecución a la que apunta Zenbleed

  • Los CPU x86-64 tienen registros vectoriales XMM de 128 bits, y los CPU modernos los amplían hasta YMM de 256 bits y ZMM de 512 bits
  • Los registros vectoriales se usan no solo para cálculo numérico, sino también en funciones de la biblioteca estándar de C de glibc como strcmp, memcpy y strlen
  • La implementación optimizada con AVX2 de strlen en glibc combina varias instrucciones vectoriales para encontrar la posición del primer byte nul en una cadena
    • vpxor xmm0,xmm0,xmm0 pone en 0 la parte inferior de ymm0
    • vpcmpeqb ymm1,ymm0,[rdi] compara los bytes de la cadena con bytes 0
    • vpmovmskb eax,ymm1 mueve el resultado de la comparación a un registro general
    • tzcnt eax,eax calcula la posición del primer byte nul

vzeroupper y el archivo de registros

  • vzeroupper es una instrucción que pone en 0 los bits superiores de los registros vectoriales
  • Si se mezclan registros XMM y YMM, el registro XMM puede promoverse al ancho completo, y en ese proceso pueden aparecer dependencias de bits superiores
  • glibc usa vzeroupper para evitar stalls innecesarios y hacer que los resultados posteriores no dependan de los bits superiores
  • El CPU no coloca cada registro en una ubicación física fija, sino que administra la asignación de registros físicos mediante el Register File y la Register Allocation Table
  • Al poner en 0 un registro XMM, el CPU puede no almacenar los bits reales y en su lugar marcar un indicador z-bit en la RAT
    • Este indicador puede aplicarse de forma independiente a las partes superior e inferior de un registro YMM
    • vzeroupper puede establecer el z-bit y luego liberar ese recurso en el archivo de registros

La vulnerabilidad en la recuperación de ejecución especulativa

  • Los CPU modernos usan ejecución especulativa, así que las operaciones ejecutadas en una rama mal predicha deben revertirse
  • El problema es que, cuando se recupera un vzeroupper mal predicho después de haberse ejecutado, revertir solo el z-bit no restaura correctamente el estado del recurso del archivo de registros que ya fue liberado
  • Con una programación temporal precisa, se puede hacer que algunos procesadores se recuperen de forma incorrecta de un vzeroupper mal predicho
  • Esta técnica corresponde a CVE-2023-20593 y afecta a toda la familia 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

Condiciones del ataque y alcance de la filtración

  • Para activar el bug, XMM Register Merge Optimization, el renombrado de registros y un vzeroupper mal predicho deben ocurrir consecutivamente dentro de una ventana de tiempo precisa
  • La secuencia de instrucciones de ejemplo usa la siguiente estructura
    • vcvtsi2s{s,d} provoca la merge optimization
    • vmovdqa provoca el renombrado de registros
    • Si una rama condicional es taken pero el CPU predice la ruta not-taken, vzeroupper se ejecuta de forma mal predicha y se activa el bug
  • Como operaciones básicas como strlen, memcpy y strcmp también usan registros vectoriales, pueden quedar expuestas a observación en cualquier parte del sistema donde se ejecuten
  • Como el archivo de registros se comparte dentro del mismo núcleo físico, también entran en el alcance otras VM, sandboxes, contenedores y procesos
  • Los dos hyperthreads comparten el mismo archivo de registros físicos
  • Una variante optimizada del ataque puede filtrar cerca de 30 KB por segundo por núcleo, velocidad suficiente para monitorear claves criptográficas y contraseñas de usuarios con sesión iniciada
  • El aviso técnico y el código relacionado están publicados en el repositorio de investigación de seguridad de Google
  • El código de prueba se ofrece para Linux, pero el bug no depende de un sistema operativo específico, así que todos los sistemas operativos están afectados

Método de descubrimiento: fuzzing de CPU y Oracle Serialization

  • La vulnerabilidad fue descubierta mediante fuzzing
  • La industria de CPU también realiza validación posterior al silicio (Post-Silicon Validation) para encontrar fallas de hardware después de fabricar el silicio
  • A diferencia del fuzzing tradicional basado en cobertura, en los CPU no existe una métrica que corresponda directamente a la cobertura de código
  • En su lugar, se usan performance counters para dar al fuzzer retroalimentación sobre eventos arquitectónicos interesantes
    • Con este método se pueden explorar secuencias de instrucciones difíciles de encontrar por casualidad
    • Fue posible descubrir automáticamente funciones como merge optimization
  • El fuzzing de software normalmente busca crashes, pero en programas de CPU generados aleatoriamente un crash puede ser en sí mismo un comportamiento correcto
  • Uno de los enfoques existentes, reversi, genera una operación inversa para cada instrucción aleatoria y verifica si el estado final difiere del estado inicial
    • En arquitecturas CISC como x86, la generación de casos de prueba se vuelve más compleja
  • Otro método consiste en usar un oracle para comparar el resultado del CPU bajo prueba con el de otro CPU o un simulador
  • Oracle Serialization combina ambas ideas
    • Genera un programa aleatorio y luego lo transforma automáticamente a una forma serializada
    • Agrega elementos de serialización como store/load barrier, speculation fence y cache line flush
    • Aunque el programa original y el serializado tengan características de rendimiento distintas, deben producir la misma salida
  • Si el estado final no coincide, puede tratarse de un error de ejecución microarquitectónica, y esa discrepancia llevó al descubrimiento de Zenbleed

Mitigación y límites de detección

  • La vulnerabilidad fue reportada a AMD el 15 de mayo de 2023
  • AMD distribuyó una actualización de microcódigo para los procesadores afectados
  • Es posible que el proveedor del BIOS o del sistema operativo ya haya ofrecido un parche que incluya esa actualización
  • La mitigación recomendada es aplicar la actualización de microcódigo
  • Cuando no se pueda aplicar la actualización, se puede usar como solución temporal de software configurar el chicken bit DE_CFG[9]
    • Puede implicar un costo de rendimiento
    • En Linux se puede configurar en todos los núcleos con msr-tools
    • En FreeBSD se usa cpucontrol(8)
    • Si no se sabe cómo configurar el MSR en otros sistemas operativos, se requiere soporte del proveedor
  • Desactivar SMT por sí solo no es suficiente
  • No se conoce una técnica confiable para detectar este ataque
    • Porque no requiere llamadas especiales al sistema ni privilegios
    • Tampoco es posible detectar estáticamente el uso inapropiado de vzeroupper

1 comentarios

 
GN⁺ 2023-07-25
Comentarios de Hacker News
  • Esto es realmente genial, y podría convertirse en el ejemplo clásico de que ejecutarlo en una VM no significa que sea seguro
    Siempre se ha sabido sobre escapes de VM, pero esto es una vulnerabilidad masiva con ejecución sencilla y gran recompensa incluso sin escape
    Que este bug se corrija con microcódigo no significa que no existan otros bugs similares. Muchos 0-day a menudo ya son conocidos por black hats mercenarios mucho antes de que se hagan públicos
    Vulnerabilidades de CPU descubiertas en los últimos años:
    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…

    • El problema es que las VM ya no son realmente máquinas virtuales
      En lugar de interpretar instrucciones con una gran sentencia switch, ejecutan instrucciones en la CPU real y dependen de algunas banderas de hardware que garantizan que los datos o las instrucciones no se superpongan. La CPU lo promete, pero en la práctica cumplir esa promesa es difícil
    • La comparación con Meltdown/Spectre puede ser un poco engañosa
      En esos casos, la CPU hizo exactamente lo que debía hacer, pero habilitó una forma de ataque totalmente nueva basada en temporización; este Zenbleed, en cambio, se parece más a un bug tradicional en el que quedan datos en registros donde no deberían estar
    • Ejecutar código no confiable en un sandbox, contenedor o VM no ha sido seguro, al menos desde Rowhammer
      Muchas de estas vulnerabilidades surgen, en mi opinión, de que el lado del software y el lado del hardware no se comunican bien entre sí. El software hace suposiciones sobre las garantías de aislamiento, y el hardware no advierte lo suficiente cuando esas suposiciones pueden aparecer
    • Al final, da la impresión de que la mayoría de estas cosas están relacionadas con la predicción de saltos
      Se siente como si la predicción de saltos fuera intrínsecamente tan compleja que siempre estará expuesta a este tipo de vulnerabilidades, o como si fuera tan distinta de la forma intuitiva en que entendemos los caminos del código y la ejecución de instrucciones que cuesta imaginar los casos límite hasta que ya es demasiado tarde
      ¿Llegará un punto en que la complejidad de la arquitectura de CPU sea demasiado difícil de razonar y aceptemos la pérdida de rendimiento de mantenerla más simple?
    • He visto a algunas empresas mezclar VM expuestas a internet/DMZ con VM internas en el mismo hipervisor
      Lo señalé y recomendé airgappearlas con un hipervisor separado, pero siempre me ignoraron. Supongo que al final será problema de ellos
  • El README del archivo tar del exploit incluye más detalles y el cronograma de divulgación
    2023-05-09 Un componente del pipeline de validación de CPU generó resultados anómalos
    2023-05-12 Se logró aislar y reproducir el problema; la investigación continuó
    2023-05-14 Se determinó el alcance y la gravedad del problema
    2023-05-15 Se redactó un breve informe de estado y se compartió con AMD PSIRT
    2023-05-17 AMD confirmó el reporte y reconoció que era reproducible
    2023-05-17 Se completó el desarrollo de una PoC confiable y se compartió con AMD
    2023-05-19 Se empezó a notificar a los principales proveedores de kernel e hipervisores
    2023-05-23 Se recibió de AMD una actualización beta de microcódigo para Rome
    2023-05-24 Se confirmó que la actualización corregía el problema y se notificó a AMD
    2023-05-30 AMD informó que había enviado un aviso de seguridad a sus socios
    2023-06-12 Reunión con AMD para discutir el estado y los detalles
    2023-07-20 AMD publicó el parche sin previo aviso antes de la fecha de embargo acordada
    2023-07-21 Como la corrección ya era pública, se propuso avisar en privado a las principales distribuciones para que prepararan actualizaciones de paquetes de firmware
    2023-07-24 divulgación pública

  • Esto da muchísimo miedo. En mi equipo Zen 2, un Ryzen 3600, ejecuté el exploit como usuario sin privilegios y, al copiar y pegar una cadena en el editor de texto en segundo plano (Kate), fragmentos de esa cadena quedaron registrados en la salida de zenbleed en cuestión de segundos
    Por suerte, este exploit parece depender mucho de una rutina específica en ensamblador, así que explotarlo desde JS o WASM en el navegador parece muy difícil. Si no fuera así, bastaría con dejar una pestaña maliciosa abierta en segundo plano durante unas horas para filtrar datos fácilmente
    Estoy esperando a que el mantenedor de Fedora distribuya el nuevo microcódigo para que el kernel pueda actualizarlo durante el arranque

    • Al menos una persona aquí dice que también pudo reproducirlo con JavaScript: https://news.ycombinator.com/item?id=36849767
    • También lo probé en mi equipo Zen 2, y el mismo ataque funciona incluso ejecutándolo dentro de KVM
    • Si alguien encuentra una forma de hacerlo en JS, parece probable que pueda aplicarse bastante ampliamente
      Al mismo tiempo, ojalá V8 y SpiderMonkey incorporen antes y además mitigaciones por software
      Aun así, un exploit en JS también necesitaría una forma de exfiltrar los datos, y parece bastante difícil ocultar eso por completo
    • No sé cómo compilar la PoC. En Ubuntu me sale "No such file or directory" y error 127
  • Se siente como que no es coincidencia que OpenBSD haya añadido carga de microcódigo AMD en los últimos 3 días
    https://news.ycombinator.com/item?id=36838511

  • La afirmación de que AMD publicó una actualización de microcódigo para los procesadores afectados no parece del todo precisa.
    AMD publicó una actualización de microcódigo[0] para los modelos 0x31 y 0xa0 de la familia 17h, que según WikiChip[1] corresponden a Rome, Castle Peak y Mendocino.
    Hasta ahora, no parece haber actualizaciones de microcódigo para Renoir, Grey Hawk, Lucienne, Matisse ni Van Gogh. Por suerte, el kernel nuevo puede simplemente activar el chicken bit para ellos, y de hecho lo hace[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...

  • Viendo la parte relevante, esta técnica es CVE-2023-20593, funciona en todos los procesadores de clase Zen 2 y al menos incluye los siguientes productos:
    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

    • Me pregunto si eso significa “solo se confirmó en Zen 2”, o si realmente quiere decir que el problema está definitivamente limitado a esa arquitectura.
      ¿Será que la misma técnica, o una similar, podría funcionar también en núcleos Zen/Zen+ anteriores o en los Zen 3 posteriores, pero todavía no lo han demostrado?
    • Parece que mi 2700X se salvó por muy poco. Asumiendo que la serie 7020 está afectada y la serie 7000 no, entonces sí.
    • Me pregunto qué pasa con PlayStation 5. Lo mismo con Xbox y ese aparato de Valve.
    • ¿Ryzen 5000 sin Radeon no es vulnerable? Esos procesadores parecen ser Zen 3.
      Mi AMD Ryzen 9 5950x Desktop Processor también parece ser Zen 3, así que supongo que está bien.
      No es que ejecute cargas no confiables, pero dicen que la suerte favorece a los preparados.
    • Como referencia, los Ryzen 3000 APU no son Zen 2.
  • El sitio se está cayendo por el tráfico: https://web.archive.org/web/20230724143835/https://lock.cmpx...

    • Es solo una página HTML estática, así que no entiendo cómo en 2023 un sitio estático puede caerse por tráfico.
      En la mayoría de los casos, el tráfico de HN casi nunca llega ni a 100 páginas vistas por segundo.
    • Enlace más rápido: https://archive.is/QAwvQ
    • El original al final sí carga. Puede depender del entorno.
  • https://www.amd.com/en/resources/product-security/bulletin/a...
    Según el boletín de seguridad de AMD, las actualizaciones de firmware para CPU que no son EPYC no llegarán hasta fin de año. ¿Hasta entonces los usuarios tienen que desactivar el chicken bit y asumir la pérdida de rendimiento?

    • ¿AMD está en sus cabales? Esto no es de gravedad media.
  • Tan impresionante como aterrador. Corrí una muestra de 10 MB durante un minuto y pude “filtrar” partes de mi contraseña de Bitwarden, mi contraseña de inicio de sesión por ssh y fragmentos de credenciales bancarias, y fue fácil reconstruirlos.

  • El artículo estuvo realmente muy bueno. Me gustó especialmente la parte donde se aborda cómo se puede determinar si un programa de generación aleatoria se ejecutó correctamente.
    El enfoque obvio es ejecutarlo en un oráculo, como otro procesador o un simulador, para ver si se comporta de la misma manera.
    Pero para verificar efectos microarquitectónicos dentro de una ventana de tiempo estrecha, también se puede escribir el mismo programa insertando varios stall, fence, nop, etc. En código de un solo hilo eso no debería afectar la salida, pero dentro del CPU termina haciendo cosas bastante distintas a nivel microarquitectónico. De esa forma, el CPU puede convertirse en su propio oráculo.

    • Esta parte fue realmente interesante, y me gustó en especial la diferencia entre el fuzzing de software y el fuzzing de hardware.
      También me gustó lo de chicken bit