2 puntos por GN⁺ 2024-10-08 | 2 comentarios | Compartir por WhatsApp
  • Se logró un experimento de escalada local de privilegios que, usando solo un encendedor de cigarrillos piezoeléctrico para inducir fallas electromagnéticas en el bus de memoria DDR3 de una laptop, pasó de un usuario de Linux sin privilegios a una shell root
  • En una laptop Samsung S3520 se soldó una resistencia de 15Ω y un cable que actúa como antena al pin de datos de un SODIMM, y al accionar el encendedor cerca se generaron errores de memoria que invertían bits específicos
  • En el experimento con CPython, una falla en la línea DQ7 invirtió el bit 7 del puntero de un objeto para hacer que referenciara una estructura falsa de bytearray dentro de bytes, construyendo primitivas de lectura/escritura arbitraria de memoria
  • La escalada de privilegios en Linux funciona rociando la memoria física con grandes cantidades de tablas de páginas y luego provocando una falla en el bit 29 durante la lectura de una PTE, para que un mapeo accesible por el usuario apunte a una tabla de páginas
  • Tras lograrlo, se encontró la primera página de /usr/bin/su en memoria física y se reemplazó por un pequeño ELF setuid root, contaminando la page cache; en el entorno de prueba, la confiabilidad percibida fue de alrededor del 50% por SSH y cerca del 20% en una shell gráfica

Punto de partida del experimento de EMFI con encendedor

  • Incluso cuando no hay bugs de software, se puede provocar un comportamiento excepcional mediante inyección de fallas (fault injection)
    • Entre los métodos de inyección de fallas están la corrupción de datos de control por software, glitches de alimentación, glitches de reloj, pulsos electromagnéticos y láseres
  • La inyección de fallas por hardware normalmente requiere precisión en el momento y el lugar donde se introduce la falla, por lo que suele necesitar equipo especializado y costo elevado
  • El punto de partida fue acoplar un encendedor piezoeléctrico de BBQ a un inductor para usarlo como una herramienta de inyección electromagnética de fallas (EMFI) de bajo presupuesto
    • Antes ya se había logrado atacar una implementación de AES en software ejecutándose en Arduino mediante DFA
  • En el contexto de que el anuncio de Nintendo Switch 2 parecía cercano, y anticipando software de sistema similar al de Switch 1 junto con una escasez de bugs de software, se retomaron los experimentos de EMFI de bajo costo

Objetivo de prueba y falla en el bus DDR

  • El equipo de prueba fue una laptop Samsung S3520 fabricada en 2011 con CPU Intel i3-2310M y 1GB de RAM DDR3
    • Se eligió porque puede ejecutar Arch, una distribución ligera de Linux de escritorio, y porque no sería tan grave dañarla
  • El objetivo era escribir un exploit de escalada local de privilegios que funcionara a partir de una falla de hardware inyectada
  • Se eligió como punto físicamente más vulnerable el bus DDR que conecta la memoria DRAM con el sistema
    • En un SODIMM hay 64 pines DQ, de DQ0 a DQ63, que transportan los bits de datos de lectura/escritura
  • El dispositivo experimental consistió en soldar una resistencia de 15Ω y un cable a un pin estimado como DQ26
    • El cable actúa como antena y capta interferencia electromagnética del entorno para transmitirla al bus de datos
    • La resistencia limita la intensidad de la interferencia para no perturbar continuamente el funcionamiento normal de la memoria, aunque puede que en la práctica no sea necesaria
  • Solo con accionar un encendedor piezoeléctrico común cerca del cable-antena aparecían errores de memoria de forma estable en memtest
    • Todos los errores mostrados eran inversiones del bit 29
    • Aunque el pin soldado se estimó como DQ26, que se invirtiera el bit 29 podría deberse a que se contó mal el pin o a que la placa madre redirige las líneas de datos
  • Como el tiempo de reacción es del orden de la velocidad de un dedo, el control de timing de la inyección de fallas no es preciso
    • Cuando ocurre una falla, es probable que el mismo bit se invierta en una lectura o escritura específica de 64 bits

Abuso de bit flips en CPython

  • El primer experimento fue crear un exploit tipo escape de sandbox en CPython
    • Como CPython en sí no es un sandbox, no se trata realmente de evadir un límite de seguridad, sino de una etapa preparatoria usando estructuras internas conocidas
  • En este experimento se usó un cable soldado a DQ7 en lugar del DQ26 de la foto anterior
  • Los objetos de CPython están en el heap del recolector de basura, y el encabezado del objeto contiene el refcount y un puntero al objeto de tipo, seguidos por campos según el tipo
    • Un objeto bytes contiene sus propios datos en la misma asignación del heap, después del campo de longitud
    • Un objeto bytearray tiene, después del campo de longitud, un puntero al búfer donde se almacenan los datos reales
  • La estrategia clave consiste en colocar una estructura falsa de bytearray como datos dentro de un objeto bytes
    • Si se engaña a CPython para que entregue una referencia a ese objeto falso, se puede lograr lectura/escritura arbitraria de memoria usando los campos de longitud y puntero del bytearray elegido por el atacante
  • Una falla que invierte el bit 7 tiene el efecto de sumar o restar 128 a un puntero dentro de una palabra de 64 bits
    • Si el bytearray falso se coloca con un offset de +128 bytes dentro del objeto bytes, el puntero al objeto bytes puede convertirse por la falla en un puntero al bytearray falso
    • Esa conversión ocurre en la dirección deseada con una probabilidad del 50%
  • Es importante que no se está alterando el contenido de la memoria en sí, sino haciendo glitch sobre operaciones de lectura/escritura del bus de memoria
    • A diferencia de Rowhammer, no cambia el dato almacenado, sino que se corrompe un acceso en tránsito por el bus
  • Para que el acceso al puntero deseado represente la mayor parte de la actividad del bus, se llenó una tupla grande con referencias al mismo objeto
    • Como la caché de CPU reduce los accesos a DRAM, se hace acceso secuencial a una estructura mayor que la caché de 3MiB para forzar lecturas desde DRAM en cada ocasión
    • is en Python funciona como una comparación de punteros y se usa para verificar si el puntero cambió
  • El código fuente completo del exploit de CPython está en ddr3_dq7.py
    • La variable TESTING permite simular bit flips en software sin hardware

Estructuras de memoria necesarias para la escalada en Linux

  • En la escalada local de privilegios en Linux, las estructuras clave son la caché, la memoria virtual, las tablas de páginas y la TLB
  • Como la DRAM es relativamente lenta, la CPU usa cachés L1, L2 y L3
    • La caché L3 de la laptop de prueba es de 3MiB
    • Si hay cache hit no se accede a DRAM, y solo un cache miss provoca una lectura desde DRAM
  • La unidad mínima desde el punto de vista de la caché es la cache line, que en esta laptop es de 64 bytes
    • Aunque se lea un solo byte, si el dato no está en caché se produce una lectura de 64 bytes desde DRAM
    • Como el bus de datos DDR tiene 64 bits de ancho, esa lectura se procesa como un burst de 8 accesos secuenciales
  • La memoria virtual en x86-64 se implementa con páginas de 4KiB y tablas de páginas en forma de árbol
    • Esta plataforma tiene tablas de páginas de 4 niveles
    • Cada tabla de páginas ocupa una página de 4KiB y contiene 512 PTE de 64 bits
    • Las PTE de niveles superiores apuntan a la dirección física de la tabla de páginas del siguiente nivel, y las PTE de nivel 0 apuntan a la página física objetivo
    • La dirección física de la tabla de páginas raíz se guarda en el registro de CPU CR3
  • La parte importante de una PTE aquí es el campo de dirección física
    • Al enmascarar los bits de flags queda la dirección de memoria física alineada a página
  • La TLB es hardware interno de la CPU que cachea los mapeos de direcciones virtuales a físicas
    • No se conoce el tamaño exacto de la TLB en la laptop de prueba, pero parece rondar unas 1024 entradas

Llevar las tablas de páginas a memoria de usuario

  • La estrategia del exploit para Linux se inspira en elementos del exploit de Rowhammer de Mark Seaborn
  • El objetivo es mapear las tablas de páginas del propio proceso en memoria accesible por el usuario
    • Si se logra, se pueden modificar las PTE para acceder a memoria física arbitraria
  • En vez de controlar con precisión el layout de la memoria física, se llena exactamente el 50% de la memoria física con tablas de páginas de nivel 0
  • Luego se accede repetidamente a mapeos R/W para evitar la TLB
    • Como la cantidad de mapeos supera el tamaño de la TLB, cada acceso puede forzar un recorrido de tabla de páginas
    • Durante ese recorrido, el objetivo es provocar una falla del bit 29 al leer una PTE de nivel 0
  • Si se invierte el bit 29, la dirección física a la que apunta la PTE cambia en un offset de 512MiB
    • Con suerte, la nueva dirección apuntará a una de las tablas de páginas de nivel 0 rociadas antes
    • En ese caso, un mapeo que normalmente debería verse como una página R/W común expone una tabla de páginas como si fuera una página R/W normal
  • En teoría, cualquier inversión de bit desde el 29 hasta el 12 podría funcionar
    • El bit 12 corresponde a un offset de 4KiB
    • La clave es que la PTE apunte a “otro lugar” y que alrededor del 50% de la memoria física esté lleno de tablas de páginas aprovechables
  • Puede que soldar el cable-antena no sea estrictamente necesario
    • Si se pudiera generar una interferencia electromagnética lo bastante fuerte quizá sería posible, pero la probabilidad de crash o daño del sistema sería mucho mayor

Método de rociado de tablas de páginas de nivel 0

  • Primero se crea un archivo en memoria con memfd_create
    • Cumple el mismo papel que el archivo en /dev/shm/ del exploit de Mark Seaborn, pero sin tocar directamente el sistema de archivos
  • El mismo búfer se mapea muchas veces con mmap
    • La opción MAP_FIXED fuerza que cada mapeo quede alineado a 2MiB en la memoria virtual
    • Esa alineación garantiza la creación de una nueva tabla de páginas de nivel 0 en cada ocasión
  • Linux tiene un límite por proceso de aproximadamente 2^16 mapeos, es decir, VMA
    • Cada mapeo se hace de 32MiB de longitud para que uno solo cree 16 tablas de páginas de nivel 0
  • Cada mapeo ocupa 32MiB en el espacio de direcciones virtuales, pero sus PTE apuntan a la misma página física
    • El costo en memoria física corresponde solo a las tablas de páginas de nivel 0
    • De esta forma se pueden rociar tablas de páginas hasta llenar la memoria

Lectura/escritura de memoria física y contaminación de la page cache de su

  • Mientras se espera la falla, se accede repetidamente a los mapeos R/W y se detecta la falla cuando se devuelve un valor distinto del esperado
    • Si los datos devueltos parecen una PTE, eso indica que ya se obtuvo acceso R/W a una tabla de páginas
  • El siguiente paso es averiguar a qué dirección virtual corresponde esa tabla de páginas
    • Se modifica la PTE para que apunte a la dirección física 0
    • Luego se vuelve a escanear los mapeos R/W para encontrar cuál cambió
  • Aunque se modifique una PTE, la MMU no se da cuenta de inmediato
    • Eso se debe a que el mapeo virtual-físico está cacheado en la TLB
    • Como no se conoce una forma de hacer flush de la TLB directamente desde espacio de usuario, se accede repetidamente a miles de mapeos R/W para llenarla con nuevos valores y expulsar los anteriores
  • En este punto ya es posible leer y escribir sobre toda la memoria física
  • Después se abre el ejecutable /usr/bin/su en modo de solo lectura y se hace mmap de su primera página
    • /usr/bin/su es un ejecutable setuid root
    • Se escanea toda la memoria física para encontrar esa misma página
    • Una vez hallada, se escribe sobre esa página física y se reemplaza por un ELF payload de menos de 4KiB que abre una shell root
  • La siguiente vez que Linux ejecuta su, considera que su primera página ya está en memoria y no la vuelve a leer desde disco
    • Reutiliza la page cache contaminada y ejecuta el ELF inyectado
    • El ELF inyectado vacía la page cache con echo 1 > /proc/sys/vm/drop_caches, para que la siguiente ejecución de su vuelva a funcionar normalmente
  • El código fuente completo del exploit para Linux está en linux_x86_64_lpe.c

Confiabilidad y limitaciones del entorno

  • En la ejecución de la demo hubo suerte y un solo clic del encendedor produjo un glitch favorable
    • En varios intentos anteriores, todo el sistema se había caído
  • La confiabilidad total del exploit no se midió rigurosamente
    • Con la pantalla de la laptop apagada y conectado por SSH, la percepción fue de alrededor del 50%
    • En una shell gráfica, parecía más cercana al 20%
  • El sistema experimental usaba gráficos integrados
    • Es posible que los accesos de memoria de la GPU interfieran con el exploit
  • También estaban activos servicios en segundo plano relacionados con pipewire, sshd, systemd y swap
    • Fue una decisión para mantener un entorno de Linux de escritorio realista, y desactivarlos podría mejorar la confiabilidad
  • Si hubiera habido más RAM instalada, se habría podido llenar una mayor proporción con tablas de páginas, aumentando la confiabilidad global

Posibles usos y preguntas pendientes

  • Si fuera posible una escalada local de privilegios por EMFI con alta confiabilidad en Windows, podría afectar escenarios donde anticheats basados en TPM limitan el software permitido por el sistema
  • Algo similar podría plantearse con verificaciones de SafetyNet o Play Integrity en Android, aunque insertar un modchip de glitch en un teléfono es bastante más difícil
  • En optimización de rendimiento de bajo nivel, muchas veces el conocimiento de tablas de páginas y TLB no es directamente crucial, pero en este exploit la propia estructura que mantiene la ilusión de memoria virtual se convierte en el objetivo del ataque
  • Todavía queda mucho por verificar sobre su alcance
    • Si funciona también en DDR4 y DDR5
    • Si funciona también en ARM
    • Hasta qué punto distintos tipos de ECC, en especial DDR5 Link-ECC, lo mitigan
    • Cuál sería la forma más simple de disparar fallas similares electrónicamente con un dispositivo como RP2040
    • Si se puede usar para escapar de un hipervisor
    • Si se puede convertir en un exploit de WebKit o en un exploit del kernel de Nintendo Switch

2 comentarios

 
mammal 2024-10-08

Me recuerda a sacar el encendedor de un lighter para subir monedas en las maquinitas.

 
GN⁺ 2024-10-08
Opiniones en Hacker News
  • La inspiración aquí era obtener acceso root en la Switch 2, y haber conseguido root en Linux fue una prueba de concepto.
    El objetivo no era tanto mostrar una vulnerabilidad de seguridad fundamental explotable en la práctica, sino recuperar la propiedad real de tu propio hardware sin romper un TPM ni el anticheat con privilegios de kernel de un juego.

    • Entiendo la intención, pero no termino de ver el punto. Tenía más sentido hace 20 años, cuando las consolas eran computadoras potentes que se vendían con pérdida o con márgenes bajos, pero hoy Nintendo vende sus consolas con ganancia y es muy probable que la Switch 2 también.
      Es un trabajo impresionante y celebro que se defienda la libertad del software, pero preferiría apoyar alternativas. ¿Por qué darles ganancias y números que parezcan una base instalada? Mejor comprar una Steam Deck u otro dispositivo portátil que ofrezca acceso root como función desde el principio.
  • El artículo está muy bien escrito y el desafío es enorme, pero mi cabeza reacciona desde el sentido común del hacking: “si hay acceso físico, ya se acabó”.
    Lo primero que se me ocurrió fue que, con acceso físico, podrías reflashear el BIOS, instalar un backdoor en un driver, arrancar con un live OS y manipular /etc/{passwd,shadow,groups, etc}.
    Pero luego recordé que, si el disco está cifrado, la mayoría de los ataques con acceso físico dejan de ser posibles, y entonces este tipo de ataque se vuelve tremendamente atractivo. La idea de la antena podría extenderse a hardware con un dispositivo de interferencia incorporado, e incluso hacerlo comunicarse con el exterior por un medio inalámbrico para que el atacante pueda provocar la interferencia de forma remota. Si a eso se suma un sitio web controlado por el atacante al que se engaña a la víctima para que entre, empieza a verse realista.

    • La motivación de la introducción es rootear/jailbreakear una consola portátil de videojuegos. Es un caso totalmente plausible: tienes acceso físico, pero aun así quieres obtener un acceso “no autorizado”.
    • En mi opinión, reflashear el BIOS no te serviría de mucho. Antes de que empiece la ejecución, el hardware de la CPU verifica que haya una firma con la clave privada correcta, así que primero tendrías que firmarlo.
      Esta técnica de interferencia electromagnética engaña a la propia CPU, así que no veo bien cómo podrían arreglarla salvo que aparezca un nuevo algoritmo de paginación.
    • “Si el disco está cifrado, la mayoría de los hackeos con acceso físico son imposibles” solo es cierto si la PC está apagada y todavía no se usó el keyfile o la frase de contraseña para descifrar los datos y arrancar el sistema.
      Mi PC también usa cifrado de disco completo, pero al arrancar se usa el keyfile para descifrar, y desde ese momento vuelve a ser una PC físicamente accesible.
  • Me gusta. La idea central es que ocurre un volteo de bits electrostático durante una lectura o escritura de memoria y, si además sueldas algo, puedes convertir de forma determinista un puntero “seguro” en el puntero malicioso que quieres.
    Históricamente, la postura frente al acceso físico era: “si el otro tiene el dispositivo en la mano, se acabó el juego”. Los TPM y los entornos de ejecución confiables cambiaron esa postura a: “aunque el usuario tenga acceso físico, ciertas operaciones dentro del enclave pueden considerarse confiables”.
    El siguiente paso es lo más interesante. ¿Se podrían obtener resultados razonablemente confiables sin soldar? Parece mucho más difícil, porque ya se pensó mucho en cómo lidiar con la interferencia eléctrica, pero quizá sea posible. Si cada vez que accionas el encendedor se voltea 1 bit aleatorio en una lectura de 64 bits, y el exploit funciona, por ejemplo, con cualquiera de 4 bits volteados, la cantidad promedio de intentos quizá no sea tan alta.

    • Si tienes acceso físico suficiente para soldar una antena, podrías conectar desde “atrás” un DIMM personalizado y programable y romper un TPM o lo que sea.
      Como podrías cambiar cualquier parte de la memoria al valor que quieras en el momento que quieras, no hace falta depender de volteos de bits aleatorios. Simplemente inyectas el programa completo.
    • Sin antena, creo que sería difícil limitar el volteo a un solo bit. Al menos esa es mi suposición.
  • Solo por el título, pensé que era un artículo sobre alguien que había obtenido acceso root en un encendedor de cigarrillos, y estaba totalmente listo para creerlo.
    El horno de mis padres recibe actualizaciones de software con regularidad, así que ni siquiera habría dudado de que un encendedor pudiera ser “smart”.

    • Por el título, medio esperaba una versión incendiaria del criptoanálisis con manguera de goma.
    • Me pregunto cómo sería un encendedor con un pequeño panel solar y batería, que detecte un cigarrillo o puro cercano con lidar y lance una chispa como un mini táser. Que no reaccione ante dedos ni hot dogs, sin botones y sin tener que recargar jamás el combustible del encendedor.
      Obviamente también necesitaría un chip para manejar el lidar y, al mismo tiempo, producir un flash LED intenso con desvanecimiento, impacto háptico y efectos de sonido. Ojalá alguien haga una demo. Estaría bueno que pareciera un pequeño revólver, aunque para la seguridad de dedos y hot dogs habría que reforzar el controlador de memoria virtual.
    • El cautín que uso más seguido también ejecuta firmware modificable en un SoC RISC-V. (https://pine64.com/product/pinecil-smart-mini-portable-solde...)
      Quién diría que derretir estaño podía ser tan complejo. Por eso también podría creer perfectamente un artículo sobre rootear un encendedor.
    • Pensé que iba a calcular raíces cuadradas con la forma de la llama.
  • Me recuerda a un exploit que se hacía en las máquinas de arcade de Sídney en los 80 y 90. Las estufas de gas de la escuela tenían un encendedor piezoeléctrico que nosotros llamábamos “clicker”, y se podía quitar de la estufa.
    Llevabas ese clicker al arcade del barrio, hacías clic en una de las esquinas del CRT y el sistema recibía una descarga que aumentaba los créditos del juego. Supongo que era porque la tierra del CRT compartía físicamente el mismo cable de tierra que el dispositivo que verificaba las monedas.
    Con el tiempo los dueños se dieron cuenta y agregaron algo tipo alarma, pero hasta entonces fueron tiempos gloriosos.

    • A principios de los 80 hacíamos exactamente lo mismo, pero usábamos el clicker de un encendedor desechable.
      Lo hicimos durante años hasta que los dueños se dieron cuenta y empezaron a cubrir los gabinetes de las máquinas con plástico transparente. Al mismo tiempo, como los gabinetes quedaron sellados con plástico, les hicieron agujeros atrás para ventilación, y descubrimos que con una vara de bambú podíamos presionar la palanca que registraba la inserción de monedas.
      Entonces movieron las ventilas hacia arriba en vez de dejarlas atrás, para que no se pudiera alcanzar la palanca, pero esta vez descubrimos que si empujabas una moneda hacia arriba por la ranura de devolución podías tocar la palanca de registro de monedas, así que los juegos gratis continuaron. Al final metieron tornillos filosos dentro de la caja de devolución para cortarte los dedos, y después de eso nos compramos una SEGA. Fue muy divertido.
    • Me acuerdo de una máquina en la que, si mi amigo se metía detrás y apagaba y encendía la corriente, aparecía un token gratis.
      No sé si estaba diseñada así a propósito para que el personal pudiera probarla gratis, pero mi amigo se arrastraba por detrás y seguía jugando gratis.
    • También funcionaba en Estados Unidos. Para los años 90, la mayoría de los arcades usaban tokens propios en vez de monedas en efectivo, y también había muchas máquinas de juego de habilidad con apuestas donde los tokens se apilaban en fila y se deslizaban.
      En la versión “Jungle Jive”, si le dabas una pequeña descarga a la ranura metálica con el encendedor eléctrico de un cigarrillo, salían tokens del otro lado de la máquina. Si hacías demasiados clics muy rápido, entraba en modo de alerta. Se podía hacer solo, pero la configuración óptima era un equipo de tres: uno vigilando a los empleados, uno haciendo clic y uno recogiendo.
    • Me viene un recuerdo borroso de que si golpeabas exactamente el costado de una máquina de pinball te daba una partida gratis. Supongo que era el mismo principio.
    • Recuerdo haber leído en este libro que el hacker Pengo era conocido por agregar créditos a máquinas de arcade de la misma manera.
      https://www.amazon.com/CYBERPUNK-Outlaws-Hackers-Computer-Fr...
  • Leído como australiano, se interpreta distinto. Dependiendo de tus habilidades de negociación, podrías conseguir root con solo un encendedor.

  • No solo es un exploit interesante, también es una gran miniintroducción a cómo funciona la caché en una CPU.
    Recuerdo que hace más o menos un año se publicó un artículo que explicaba cómo funcionan y se construyen las computadoras, empezando por la parte más pequeña: las compuertas lógicas. ¿Alguien recuerda qué sitio era?

  • “No es más que una resistencia de 15 ohmios y un cable soldados a DQ26. El cable actúa como antena, capta interferencia electromagnética cercana y la envía directo al bus de datos”.
    Es un hack realmente genial. Crear interferencia electromagnética con un encendedor. Tendré que prender fuego junto al bus DDR y ver qué pasa.

  • Claro, si primero tienes que soldar una antena a la memoria, entonces se puede :-)
    Aun así, es un artículo excelente y minucioso sobre cómo explotar este tipo de glitch en la práctica. Un encendedor también puede servir para merodear por la puerta trasera de un data center esperando a que salga un administrador a fumar.

    • “En teoría, si ocurre una inversión de bit en cualquier posición entre el bit 29 y el bit 12, funciona. Por lo tanto, si se puede generar una interferencia electromagnética lo suficientemente fuerte, quizá no sea estrictamente necesario soldar el cable de antena”.
    • Un uso en la sección de “uso práctico” es el bypass de protección anticopia en consolas.
  • Por el título, pensé que iba a ser una historia sobre hackear autos Hyundai con un dispositivo encendedor USB-C.