Вы находитесь на странице: 1из 4

buscamos en el binario compilado de la víctima y en las bibliotecas compartidas del sistema

operativo secuencias de instrucciones que se pueden usar para filtrar información del espacio de
Ataques Spectre: Explotación de la Ejecución Especulativa direcciones de la víctima. Finalmente, escribimos un programa atacante que explota la función de
ejecución especulativa de la CPU para ejecutar las secuencias encontradas previamente como
Resumen instrucciones transitorias. Con esta técnica, podemos leer la memoria del espacio de direcciones de
Los procesadores modernos utilizan la predicción y la ejecución especulativa para maximizar el la víctima, incluidos los secretos almacenados en ella.
rendimiento. Por ejemplo, si el destino de una ejecución depende de un valor de memoria que está Ataques con JavaScript y eBPF. Además de violar los límites de aislamiento del proceso usando
en proceso de lectura, las CPU intentarán adivinar el destino e intentarán ejecutarlo con código nativo, los ataques Spectre también se pueden usar para violar el área de prueba, por
anticipación. Cuando finalmente llega el valor de la memoria, la CPU descarta o confirma el cálculo ejemplo, montándolos a través de un código JavaScript portátil. Demostrando esto empíricamente,
especulativo. La lógica especulativa es no confiable en cómo se ejecuta, ya que puede acceder a la mostramos un programa JavaScript que lee con éxito los datos del espacio de direcciones del
memoria y los registros de la víctima, y puede realizar operaciones con efectos secundarios proceso del navegador que lo ejecuta. Además, demostramos ataques aprovechando el intérprete
medibles. eBPF y JIT en Linux
Los ataques de Spectre implican inducir a una víctima a realizar operaciones especulativas que no
ocurrirían durante la ejecución correcta del programa y que filtran la información confidencial de la 1.2 Nuestras técnicas
víctima a través de un canal lateral al adversario. Este documento describe los ataques prácticos que En un nivel alto, los ataques de Spectre violan los límites de aislamiento de la memoria al combinar
combinan la metodología de los ataques de canal lateral, los ataques de fallas y la programación la ejecución especulativa con la exfiltración de datos a través de canales encubiertos
orientada al retorno que puede reactivar la memoria arbitraria del proceso de la víctima. En términos microarquitectónicos. Más específicamente, para montar un ataque Spectre, un atacante comienza
más generales, el documento muestra que las implementaciones de ejecución especulativa violan localizando o introduciendo una secuencia de instrucciones dentro del espacio de direcciones del
los supuestos de seguridad que sustentan numerosos mecanismos de seguridad de software, proceso que, cuando se ejecuta, actúa como un transmisor de canal secreto que pierde la memoria
incluida la separación de procesos del sistema operativo, el uso de contenedores, la compilación de la víctima o registra el contenido. Luego, el atacante engaña a la CPU para que ejecute
justo a tiempo (JIT) y las contramedidas para el tiempo de caché y los ataques de canal lateral. Estos especulativamente y erróneamente esta secuencia de instrucciones, filtrando así la información de
ataques representan una seria amenaza para los sistemas reales, ya que se encuentran capacidades la víctima por el canal secreto. Finalmente, el atacante recupera la información de la víctima a través
de ejecución especulativa vulnerables en microprocesadores de Intel, AMD y ARM que se utilizan en del canal secreto. Si bien los cambios en el estado nominal de la CPU como resultado de esta
miles de millones de dispositivos. ejecución especulativa errónea se revierten eventualmente, la información previamente filtrada o
Si bien en algunos casos son posibles contramedidas improvisadas específicas sobre el procesador, los cambios en otros estados microarquitectónicos de la CPU, por ejemplo, el contenido de la
las soluciones requerirán correcciones a los diseños del procesador, así como actualizaciones a las memoria caché, pueden sobrevivir a la reversión del estado nominal.
arquitecturas del conjunto de instrucciones (ISA) para dar a los arquitectos de hardware y La descripción anterior de los ataques de Spectre es general, y necesita ser instanciada
desarrolladores de software una comprensión común sobre que estado de implementaciones de concretamente con una forma de inducir la ejecución especulativa errónea, así como con un canal
computo de CPU son (y cuáles no son) permitidas las fugas. secreto microarquitectónico. Si bien son posibles muchas opciones para el componente de canal
secreto, las implementaciones descritas en este trabajo utilizan canales secretos basados en caché
1. Introducción [64], es decir, Flush + Reload [74] y Evict + Reload [25, 45].
Los cálculos realizados por dispositivos físicos a menudo dejan efectos secundarios observables más Ahora procedemos a describir nuestras técnicas para inducir e influir en la ejecución especulativa
allá de los resultados nominales del cálculo. Los ataques de canal lateral se centran en explotar estos errónea.
efectos secundarios para extraer información secreta que de otro modo no estaría disponible. Desde Variante 1: Explotación de bifurcaciones condicionales.
su introducción a finales de los años 90 [43], muchos efectos físicos como el consumo de energía En esta variante de los ataques de Spectre, el atacante entrena mal al predictor de bifurcación de la
[41, 42], la radiación electromagnética [58] o el ruido acústico [20] se han aprovechado para extraer CPU para predecir erróneamente la dirección de una bifurcación, lo que hace que la CPU viole
claves criptográficas, así como otros secretos. temporalmente la semántica del programa al ejecutar código que de otro modo no se habría
Los ataques físicos de canal lateral también se pueden utilizar para extraer información secreta de ejecutado. Como mostramos, esta ejecución especulativa incorrecta permite a un atacante leer
dispositivos complejos como PC y teléfonos móviles [21, 22]. Sin embargo, debido a que estos información secreta almacenada en el espacio de direcciones del programa. De hecho, considere el
dispositivos a menudo ejecutan código de un origen potencialmente desconocido, enfrentan siguiente ejemplo de código:
amenazas adicionales en forma de ataques basados en software, que no requieren equipos de if (x < array1_size)
medición externos. Mientras que algunos ataques aprovechan las vulnerabilidades del software y = array2[array1[x] * 4096];
(como desbordamientos del búfer [5] o errores de doble libre [12]), otros ataques de software En el ejemplo anterior, suponga que la variable x contiene datos controlados por el atacante. Para
aprovechan las vulnerabilidades del hardware para filtrar información confidencial. Los ataques de garantizar la validez del acceso a la memoria de array1, el código anterior contiene una declaración
este último tipo incluyen ataques de microarquitectura que aprovechan el tiempo de caché [8, 30, if cuyo propósito es verificar que el valor de x esté dentro de un rango legal. Mostramos cómo un
48, 52, 55, 69, 74], historial de predicción de bifurcacion [1, 2], búferes de objetivo de bifurcacion atacante puede omitir esta declaración if, leyendo así datos potencialmente secretos del espacio de
[14, 44] o filas de DRAM abiertas [56 ] Las técnicas basadas en software también se han utilizado direcciones del proceso.
para montar ataques de falla que alteran la memoria física [39] o los valores internos de la CPU. Primero, durante una fase inicial de entrenamiento incorrecto, el atacante invoca el código anterior
Varias técnicas de diseño microarquitectura han facilitado el aumento de la velocidad del procesador con entradas válidas, entrenando así al predictor de bifurcacion para que espere que el if sea
en las últimas décadas. Uno de estos avances es la ejecución especulativa, que se usa ampliamente verdadero. Luego, durante la fase de explotación, el atacante invoca el código con un valor de x fuera
para aumentar el rendimiento e implica que la CPU adivine las posibles direcciones de ejecución de los límites de array1. En lugar de esperar la determinación del resultado de la bifurcacion, la CPU
futuras y ejecute prematuramente instrucciones en estos caminos. Más específicamente, considere adivina que la verificación de límites será verdadera y ya ejecuta especulativamente instrucciones
un ejemplo en el que el flujo de control del programa depende de un valor no almacenado en caché que evalúan array2 [array1 [x] * 4096] utilizando la x maliciosa. Tenga en cuenta que la lectura de
ubicado en la memoria física externa. Como esta memoria es mucho más lenta que la CPU, a menudo array2 carga datos en el caché en una dirección que depende de array1 [x] usando la x maliciosa,
toma varios cientos de ciclos de reloj antes de que se conozca el valor. En lugar de desperdiciar estos escalada para que los accesos vayan a diferentes líneas de caché y para evitar efectos de captación
ciclos al estar sin uso, la CPU intenta adivinar la dirección del flujo de control, guarda un punto de previa de hardware.
control de su estado de registro y procede a ejecutar especulativamente el programa en la ruta Cuando finalmente se determina el resultado de la verificación de límites, la CPU descubre su error
adivinada. Cuando el valor finalmente llega de la memoria, la CPU verifica la exactitud de su y revierte cualquier cambio realizado a su estado microarquitectura nominal. Sin embargo, los
suposición inicial. Si la suposición era incorrecta, la CPU descarta la ejecución especulativa incorrecta cambios realizados en el estado de la memoria caché no se revierten, por lo que el atacante puede
al revertir el estado del registro al punto de control almacenado, lo que resulta en un rendimiento analizar el contenido de la memoria caché y encontrar el valor del byte potencialmente secreto
comparable a la inactividad. Sin embargo, si la suposición fue correcta, los resultados de la ejecución recuperado en la lectura fuera de los límites de la memoria de la víctima.
especulativa se comprometen, produciendo una ganancia de rendimiento significativa ya que se Variante 2: Explotación de bifurcaciones indirectas.
realizó un trabajo útil durante el retraso. A partir de la programación orientada al retorno (ROP) [63], en esta variante el atacante elige un
Desde una perspectiva de seguridad, la ejecución especulativa implica ejecutar un programa de dispositivo del espacio de direcciones de la víctima e influye en la víctima para que ejecute el
formas posiblemente incorrectas. Sin embargo, debido a que las CPU están diseñadas para mantener dispositivo de forma especulativa. A diferencia de ROP, el atacante no se basa en una vulnerabilidad
la corrección funcional al revertir los resultados de ejecuciones especulativas incorrectas a sus en el código de la víctima. En su lugar, el atacante entrena el Branch Target Buffer (BTB) para predecir
estados anteriores, se suponía anteriormente que estos errores eran seguros. erróneamente una bifurcacion de una instrucción indirecta de bifurcación a la dirección del
dispositivo, lo que resulta en la ejecución especulativa del dispositivo. Como antes, si bien los efectos
1.1 Nuestros resultados de la ejecución especulativa incorrecta en el estado nominal de la CPU finalmente se revierten, sus
En este artículo, analizamos las implicaciones de seguridad de tal ejecución especulativa incorrecta. efectos en el caché no lo son, lo que permite que el dispositivo filtre información confidencial a
Presentamos una clase de ataques microarquitectónicos que llamamos ataques Spectre. A un alto través de un canal lateral de caché. Demostramos esto empíricamente y mostramos cómo la
nivel, los ataques de Spectre engañan al procesador para que ejecute secuencias de instrucciones selección cuidadosa de dispositivos permite que este método lea la memoria arbitraria de la víctima
especulativas que no deberían haberse ejecutado con la ejecución correcta del programa. Como los Para forzar el BTB, el atacante encuentra la dirección virtual del gadget en el espacio de direcciones
efectos de estas instrucciones en el estado nominal de la CPU se revierten, los llamamos de la víctima, luego realiza ramificaciones indirectas a esta dirección. Este entrenamiento se realiza
instrucciones transitorias. Al influir en qué instrucciones transitorias se ejecutan especulativamente, desde el espacio de direcciones del atacante. No importa qué reside en la dirección del gadget en el
podemos filtrar información desde el espacio de direcciones de memoria de la víctima. espacio de direcciones del atacante; todo lo que se requiere es que las direcciones virtuales del
Demostramos empíricamente la viabilidad de los ataques de Spectre mediante la explotación de atacante durante el entrenamiento coincidan (o alias con) las de la víctima. De hecho, siempre que
secuencias de instrucciones transitorias para filtrar información a través de dominios de seguridad el atacante maneje las excepciones, el ataque puede funcionar incluso si no hay un código asignado
tanto del código nativo no privilegiado como del código JavaScript portátil en la dirección virtual del gadget en el espacio de direcciones del atacante.
Ataques con código nativo. Como prueba de concepto, creamos un programa simple para víctimas Otras variantes. Se pueden diseñar más ataques variando tanto el método para lograr la ejecución
que contiene datos secretos dentro de su espacio de direcciones de memoria. A continuación, especulativa como el método utilizado para filtrar la información. Los ejemplos incluyen
1
instrucciones de devolución mal formadas, información de fugas a través de variaciones de tiempo Intel [35] describe que el procesador predice:
y contención en unidades aritméticas  “Llamadas y saltos directos” de manera estática o monotónica
 “Llamadas y saltos indirectos” de manera monotónica o de manera variable, que depende del
1.3. Hardware objetivo y Estado Actual comportamiento reciente del programa, y para
Hardware. Hemos verificado empíricamente la vulnerabilidad de varios procesadores Intel a los  “bifurcaciones condicionales”, el objetivo de la bifurcación y si se tomará la bifurcación.
ataques de Spectre, incluidos los procesadores Ivy Bridge, Haswell, Broadwell, Skylake y Kaby Lake. En consecuencia, se utilizan varios componentes del procesador para predecir el resultado de las
También hemos verificado la aplicabilidad del ataque a las CPU AMD Ryzen. Finalmente, también bifurcaciones. El Branch Target Buffer (BTB) mantiene una asignación de direcciones de
hemos montado con éxito los ataques Specter en varios procesadores Samsung y Qualcomm instrucciones de bifurcación ejecutadas recientemente a direcciones de destino [44]. Los
basados en ARM que se encuentran en teléfonos móviles populares. procesadores pueden usar el BTB para predecir futuras direcciones de código incluso antes de
Estado Actual. Utilizando la práctica de la divulgación responsable, grupos disjuntos de autores de decodificar las instrucciones de bifurcación. Evtyushkin et al. [14] analizó el BTB de un procesador
este documento proporcionaron versiones preliminares de nuestros resultados a grupos de Intel Haswell y concluyó que solo los 31 bits menos significativos de la dirección de la sucursal se
proveedores de CPU y otras compañías afectadas que se superponen parcialmente. En coordinación utilizan para indexar el BTB. Para las bifurcaciones condicionales, no es necesario registrar la
con la industria, los autores también participaron en una difusion de los resultados. La familia de dirección de destino para predecir el resultado de la bifurcación, ya que el destino generalmente se
ataques Spectre está documentada bajo CVE-2017-5753 y CVE-2017-5715. codifica en la instrucción mientras la condición se determina en tiempo de ejecución. Para mejorar
las predicciones, el procesador mantiene un registro de los resultados de las bifurcaciones, tanto
1.4. Meltdown para las bifurcaciones directas como indirectas recientes. Bhattacharya et al. [9] analizó la estructura
Meltdown [47] es un ataque microarquitectural relacionado que explota la ejecución fuera de orden de predicción del historial de sucursales en procesadores Intel recientes. Aunque las instrucciones
para perder la memoria del núcleo. Meltdown es distinto de los ataques de Spectre en dos formas de retorno son un tipo de bifurcación indirecta, a menudo se usa un mecanismo separado para
principales. Primero, a diferencia de Spectre, Meltdown no usa predicción de bifurcación. En cambio, predecir la dirección de destino en las CPU modernas. El Buffer de Pila de Devolución (RSB) mantiene
se basa en la observación de que cuando una instrucción causa una trampa, las instrucciones una copia de la porción utilizada más recientemente de la pila de llamadas [15]. Si no hay datos
siguientes se ejecutan fuera de orden antes de ser terminadas. En segundo lugar, Meltdown explota disponibles en el RSB, diferentes procesadores detendrán la ejecución o utilizarán el BTB como
una vulnerabilidad específica para muchos procesadores Intel y algunos procesadores ARM que respaldo [15]. La lógica de predicción de bifurcación, por ejemplo, BTB y RSB, generalmente no se
permite que ciertas instrucciones ejecutadas especulativamente eviten la protección de la memoria. comparte entre los núcleos físicos [19]. Por lo tanto, el procesador aprende solo de las bifurcaciones
Combinando estos problemas, Meltdown accede a la memoria del núcleo desde el espacio del anteriores ejecutadas en el mismo núcleo.
usuario. Este acceso provoca una trampa, pero antes de que se emita la trampa, las instrucciones
que siguen al acceso filtran el contenido de la memoria accedida a través de un canal oculto de 2.4. La jerarquía de la memoria.
caché. En contraste, Specter ataca a una gama más amplia de procesadores, incluida la mayoría de Para cerrar la brecha de velocidad entre el procesador más rápido y la memoria más lenta, los
los procesadores AMD y ARM. Además, el mecanismo KAISER [29], que se ha aplicado ampliamente procesadores usan una jerarquía de cachés sucesivamente más pequeños pero más rápidos. Los
como mitigación del ataque Meltdown, no protege contra Spectre. cachés dividen la memoria en fragmentos de tamaño fijo llamados líneas, con tamaños de línea
típicos de 64 o 128 bytes. Cuando el procesador necesita datos de la memoria, primero verifica si el
2. Antecedentes caché L1, en la parte superior de la jerarquía, contiene una copia. En el caso de un acierto en la
En esta sección, describimos algunos de los componentes microarquitectónicos de los procesadores memoria caché, es decir, los datos se encuentran en la memoria caché, los datos se recuperan de la
modernos de alta velocidad, cómo mejoran el rendimiento y cómo pueden filtrar información de los memoria caché L1 y se utilizan. De lo contrario, en el caso de una falta de memoria caché, el
programas en ejecución. También describimos la programación orientada al retorno (ROP) y los procedimiento se repite para intentar recuperar los datos de los siguientes niveles de memoria
gadgets. caché y, finalmente, la memoria externa. Una vez que se completa una lectura, los datos
generalmente se almacenan en la memoria caché (y se desaloja un valor previamente almacenado
2.1. Ejecución fuera de orden. en caché para hacer espacio) en caso de que se necesite nuevamente en el futuro cercano.
Un paradigma de ejecución fuera de orden aumenta la utilización de los componentes del Procesadores Intel modernos típicamente tienen tres niveles de caché, cada núcleo tiene cachés L1
procesador al permitir que las instrucciones más abajo en el flujo de instrucciones de un programa y L2 dedicados y todos los núcleos comparten un caché L3 común, también conocido como caché de
se ejecuten en paralelo y, a veces, antes de las instrucciones anteriores. Los procesadores modernos último nivel (LLC). Un procesador debe asegurarse de que los cachés L1 y L2 por núcleo sean
trabajan internamente con microoperaciones, emulando el conjunto de instrucciones de la coherentes utilizando un protocolo de coherencia de caché, a menudo basado en el protocolo MESI
arquitectura, es decir, las instrucciones se descodifican en microoperaciones [15]. Una vez que se [35]. En particular, el uso del protocolo MESI o algunas de sus variantes implica que una operación
han completado todos los microops correspondientes a una instrucción, así como todas las de escritura de memoria en un núcleo hará que las copias de los mismos datos en los cachés L1 y L2
instrucciones anteriores, las instrucciones pueden retirarse, confirmando sus cambios en los de otros núcleos se marquen como no válidos, lo que significa que los futuros accesos a estos datos
registros y otros estados arquitectónicos y liberando el espacio de almacenamiento intermedio de en otros núcleos no podrán cargar rápidamente los datos del caché L1 o L2 [53, 68]. Cuando esto
reordenamiento. Como resultado, las instrucciones se retiran en orden de ejecución del programa. sucede repetidamente en una ubicación de memoria específica, esto se denomina informalmente
rebote de línea de caché. Debido a que la memoria se almacena en caché con una granularidad de
2.2. Ejecución especulativa. línea, esto puede suceder incluso si dos núcleos acceden a diferentes ubicaciones de memoria
A menudo, el procesador no conoce el flujo de instrucciones futuro de un programa. Por ejemplo, cercanas que se asignan a la misma línea de caché. Este comportamiento se denomina intercambio
esto ocurre cuando la ejecución fuera de orden alcanza una instrucción de bifurcación condicional falso y es conocido como una fuente de problemas de rendimiento [33]. Estas propiedades del
cuya dirección depende de instrucciones anteriores cuya ejecución aún no se ha completado. En protocolo de coherencia de caché a veces se pueden abusar como un reemplazo para el desalojo de
tales casos, el procesador puede preservar su estado de registro actual, hacer una predicción sobre caché utilizando la instrucción clflush o patrones de desalojo [27]. Este comportamiento fue
la ruta que seguirá el programa y ejecutar instrucciones especulativas a lo largo de la ruta. Si la previamente explorado como un mecanismo potencial para facilitar los ataques de Rowhammer
predicción resulta ser correcta, los resultados de la ejecución especulativa se confirman (es decir, se [16].
guardan), lo que proporciona una ventaja de rendimiento sobre el ralentí durante la espera. De lo
contrario, cuando el procesador determina que siguió el camino incorrecto, abandona el trabajo que 2.5. Ataques de canal lateral microarquitectónicos
realizó especulativamente al revertir su estado de registro y reanudar a lo largo del camino correcto. Todos los componentes de microarquitectura que discutimos anteriormente mejoran el
Nos referimos a instrucciones que se realizan erróneamente (es decir, como resultado de una rendimiento del procesador al predecir el comportamiento futuro del programa. Con ese objetivo,
predicción errónea), pero pueden dejar rastros microarquitectónicos, como instrucciones mantienen un estado que depende del comportamiento del programa pasado y asumen que el
transitorias. Aunque la ejecución especulativa mantiene el estado arquitectónico del programa comportamiento futuro es similar o relacionado con el comportamiento pasado. Cuando varios
como si la ejecución siguiera el camino correcto, los elementos microarquitectónicos pueden estar programas se ejecutan en el mismo hardware, ya sea simultáneamente o por tiempo compartido,
en un estado diferente (pero válido) que antes de la ejecución transitoria. La ejecución especulativa los cambios en el estado microarquitectura causado por el comportamiento de un programa pueden
en CPU modernas puede ejecutar varios cientos de instrucciones por delante. El límite generalmente afectar a otros programas. Esto, a su vez, puede dar lugar a filtraciones involuntarias de información
se rige por el tamaño del búfer de reordenamiento en la CPU. Por ejemplo, en la microarquitectura de un programa a otro [19]. Los ataques iniciales del canal lateral microarquitectónico explotaron la
de Haswell, el búfer de reordenamiento tiene espacio suficiente para 192 microoperaciones [15]. variabilidad del tiempo [43] y la fuga a través del caché de datos L1 para extraer claves de primitivas
Como no existe una relación uno a uno entre el número de microoperaciones e instrucciones, el criptográficas [52, 55, 69]. A lo largo de los años, se han demostrado canales en múltiples
límite depende de las instrucciones que se utilicen. componentes microarquitectónicos, incluidos el caché de instrucciones [3], los cachés de nivel
inferior [30, 38, 48, 74], el BTB [14, 44] y el historial de ramificaciones [1, 2] . Los objetivos de los
2.3. Predicción de bifurcación. ataques se han ampliado para abarcar la detección de ubicación conjunta [59], la ruptura de ASLR
Durante la ejecución especulativa, el procesador adivina el resultado probable de las instrucciones [14, 26, 72], el control de pulsaciones de teclas [25], la impresión de dedos en el sitio web [51] y el
de bifurcación. Las mejores predicciones mejoran el rendimiento al aumentar el número de procesamiento del genoma [10]. Los resultados recientes incluyen ataques entre núcleos y CPU
operaciones ejecutadas especulativamente que pueden confirmarse con éxito. cruzados [37, 75], ataques basados en la nube [32, 76], ataques en y desde entornos de ejecución
Los predictores de bifurcación de los procesadores Intel modernos, por ejemplo, los procesadores confiables [10, 44, 61], ataques desde código móvil [23, 46 , 51], y nuevas técnicas de ataque [11,
Haswell Xeon, tienen múltiples mecanismos de predicción para bifurcaciones directas e indirectas. 28, 44]. En este trabajo, utilizamos la técnica Flush + Reload [30, 74], y su variante Evict + Reload
Las instrucciones de ramificación indirecta pueden saltar a direcciones de destino arbitrarias [25], para filtrar información confidencial. Usando estas técnicas, el atacante comienza desalojando
calculadas en tiempo de ejecución. Por ejemplo, las instrucciones x86 pueden saltar a una dirección a una línea de caché que comparte con la víctima. Después de que la víctima ejecuta durante un
en un registro, ubicación de memoria o en la pila, por ejemplo, "jmp eax "," jmp [eax] "y" ret ". Las tiempo, el atacante mide el tiempo que lleva realizar una lectura de memoria en la dirección
bifurcaciones indirectas también son compatibles con ARM (por ejemplo, "MOV pc, r14"), MIPS (por correspondiente a la línea de caché desalojada. Si la víctima accedió a la línea de caché monitoreada,
ejemplo, "jr $ ra"), RISC-V (por ejemplo, "jalr x0, x1,0") y otros procesadores. Para compensar la los datos estarán en el caché y el acceso será rápido. De lo contrario, si la víctima no ha accedido a
flexibilidad adicional en comparación con las bifurcaciones directas, los saltos indirectos y las la línea, la lectura será lenta. Por lo tanto, al medir el tiempo de acceso, el atacante aprende si la
llamadas se optimizan utilizando al menos dos mecanismos de predicción diferentes [35].
2
víctima accedió a la línea de caché monitoreada entre los pasos de desalojo y sondeo. La principal
diferencia entre las dos técnicas es el mecanismo utilizado para desalojar la línea de caché
monitoreada de la caché. En la técnica Flush + Reload, el atacante usa una instrucción de máquina
dedicada, por ejemplo, clflush de x86, para desalojar la línea. Usando Evict + Reload, el desalojo se
logra forzando la contención en el conjunto de caché que almacena la línea, por ejemplo, accediendo
a otras ubicaciones de memoria que se cargan en el caché y (debido al tamaño limitado del caché)
hace que el procesador descarte ( desalojar) la línea que se sondea posteriormente.

2.6. Programación orientada al retorno


La programación orientada al retorno (ROP) [63] es una técnica que permite a un atacante que
secuestra el flujo de control hacer que una víctima realice operaciones complejas encadenando
fragmentos de código de máquina, llamados gadgets, que se encuentran en el código del víctima
vulnerable Más específicamente, el atacante primero encuentra artilugios utilizables en el binario
Fig. 1: Antes de que el resultado correcto de la verificación de límites sea conocido, el predictor de
de la víctima. Cada gadget realiza algunos cálculos antes de ejecutar una instrucción de devolución.
rama continúa con el más probable objetivo de rama, lo que lleva a una aceleración general de la
Un atacante que puede modificar el puntero de la pila, por ejemplo, para apuntar para devolver
ejecución si
direcciones escritas en un búfer de escritura externa, o sobrescribir el contenido de la pila, por
El resultado se predijo correctamente. Sin embargo, si los límites la verificación se predice
ejemplo, usando un desbordamiento de búfer, puede hacer que el puntero de la pila apunte al
incorrectamente como verdadera, un atacante puede tener fugas información secreta en ciertos
comienzo de una serie de Direcciones de gadget elegidas de forma malintencionada. Cuando se
escenarios.
ejecuta, cada instrucción de retorno salta a una dirección de destino desde la pila. Debido a que el
La Figura 1 ilustra los cuatro casos de verificación de límites combinación con ejecución especulativa.
atacante controla esta serie de direcciones, cada retorno salta efectivamente al siguiente gadget de
Antes del resultado de se conoce la comprobación de límites, la CPU se ejecuta especulativamente
la cadena.
código que sigue la condición al predecir el más probable
Resultado de la comparación. Hay muchas razones por las cuales el resultado de una verificación de
III. RESUMEN DEL ATAQUE
límites puede no ser conocido de inmediato, por ejemplo, un error de caché antes o durante la
Los ataques de espectro inducen a una víctima a realizar especulativamente operaciones que no
verificación de límites, congestión de una unidad de ejecución requerida para los límites
ocurrirían durante el procesamiento estrictamente serializado de las instrucciones del programa, y
check, dependencias aritméticas complejas o ejecución especulativa anidada. Sin embargo, como se
que tienen fugas información confidencial de la víctima a través de un canal secreto adversario.
ilustra, una predicción correcta de la condición en estos casos conduce a una ejecución general más
Primero describimos variantes que aprovechan condicional predicciones erróneas de rama (Sección
rápida.
IV), luego variantes que aprovechan predicción errónea de los objetivos de las ramas indirectas
Desafortunadamente, durante la ejecución especulativa, el condicional la bifurcación para la
(Sección V).
verificación de límites puede seguir la ruta incorrecta.
En la mayoría de los casos, el ataque comienza con una fase de configuración, donde el adversario
En este ejemplo, suponga que un adversario hace que el código se ejecute tal que:
realiza operaciones que entrenan mal al procesador para que luego se convierta en una especulativa
• el valor de x se elige maliciosamente (fuera de los límites), como esa matriz1 [x] se resuelve en un
explícitamente errónea predicción. Además, la fase de configuración generalmente incluye pasos
byte secreto k en alguna parte en la memoria de la víctima;
que ayudan a inducir la ejecución especulativa, como manipular el estado de caché para eliminar
• array1_size y array2 no están en caché, pero k es en caché y
datos que el procesador necesitará
• las operaciones anteriores recibieron valores de x que eran válidos, liderando el predictor de rama
Determinar el flujo de control real. Durante la fase de configuración, el el adversario también puede
para asumir el if probable ser cierto.
preparar el canal secreto que se usará para extraer la información de la víctima, por ejemplo,
Esta configuración de caché puede ocurrir naturalmente o puede crearse por un adversario, por
realizando
ejemplo, al provocar el desalojo de array1_size y array2 y luego hacer que el núcleo use la clave
Enjuagar o desalojar parte de un ataque Flush + Reload o Evict + Reload.
secreta en un
Durante la segunda fase, el procesador ejecuta especulativamente instrucciones que transfieren
Operación legítima.
información confidencial de
Cuando se ejecuta el código compilado anterior, el procesador comienza comparando el valor
El contexto de la víctima en un canal encubierto de microarquitectura.
malicioso de x contra
Esto puede activarse haciendo que el atacante solicite que el la víctima realiza una acción, por
array1_size. Lectura de resultados de array1_size en un caché falla, y el procesador enfrenta un
ejemplo, a través de una llamada al sistema, un socket o un archivo. En otros casos, el atacante
retraso sustancial hasta su valor está disponible en DRAM. Especialmente si la condición de la rama,
puede aprovechar la ejecución especulativa (errónea) de su propio código para obtener información
o una instrucción en algún lugar antes de la bifurcación, espera un argumento que no se almacena
confidencial
en caché, puede tomar algún tiempo hasta que la bifurcación
Del mismo proceso. Por ejemplo, el código de ataque que es caja de arena por un intérprete,
Se determina el resultado. Mientras tanto, el predictor de rama asume que si será cierto. En
compilador justo a tiempo o "seguro" el idioma puede desear leer la memoria no se supone que
consecuencia, lo especulativo la lógica de ejecución agrega x a la dirección base de array1 y solicita
acceso. Si bien la ejecución especulativa puede exponer potencialmente datos confidenciales a
los datos en la dirección resultante de la memoria subsistema. Esta lectura es un acierto de caché y
través de una amplia gama de canales encubiertos, el ejemplos dados causa ejecución especulativa
devuelve rápidamente el valor del byte secreto k. La lógica de ejecución especulativa entonces usa
para leer primero un valor de memoria en una dirección elegida por el atacante y luego realizar una
k para calcular la dirección de array2 [k * 4096]. Eso luego envía una solicitud para leer esta dirección
operación de memoria que modifica el estado de la memoria caché de una manera que expone el
desde la memoria (lo que resulta en una pérdida de caché). Mientras que la lectura de array2 ya está
valor Para la fase final, se recuperan los datos confidenciales. Para los ataques de Spectre que utilizan
en vuelo, el resultado de la rama puede finalmente ser determinado. Los el procesador se da cuenta
Flush + Reload o Evict + Reload, el proceso de recuperación consiste en cronometrar el acceso a las
de que su ejecución especulativa fue errónea y rebobina su estado de registro. Sin embargo, la
direcciones de memoria en las líneas de caché que se están monitoreando. Los ataques de espectro
lectura especulativa
solo suponen que las instrucciones ejecutadas especulativamente pueden leer de la memoria que el
from array2 afecta el estado de la memoria caché en una dirección específica manera, donde la
proceso de la víctima podría acceder normalmente, por ejemplo, sin desencadenar una falla de
dirección depende de k.
página o una excepción. Por lo tanto, Specter es ortogonal a Meltdown [47], que explota escenarios
Para completar el ataque, el adversario mide qué la ubicación en array2 se introdujo en la memoria
en los que algunas CPU permiten la ejecución fuera de orden de las instrucciones del usuario para
caché, por ejemplo, a través de Flush + Reload o Prime + Probe. Esto revela el valor de k, ya que la
leer la memoria del kernel. En consecuencia, incluso si un procesador impide la ejecución
ejecución especulativa de la víctima se almacenó en caché
especulativa de instrucciones en los procesos del usuario para acceder a la memoria del núcleo, los
matriz2 [k * 4096]. Alternativamente, el adversario también puede usar Expulsar + Tiempo, es decir,
ataques de Spectre aún funcionan
llamar inmediatamente a la función objetivo nuevamente con un valor dentro de los límites x 'y mida
cuánto tiempo esto segunda llamada toma. Si array1 [x ’] es igual a k, entonces la ubicación
IV. VARIANTE 1: EXPLOTACIÓN DE LA RAMA CONDICIONAL MALPREDICCION
Accedido en array2 está en el caché, y la operación tiende para ser más rápido
En esta sección, demostramos cómo rama condicional la predicción errónea puede ser explotada
Muchos escenarios diferentes pueden conducir a fugas explotables usando Esta variante. Por
por un atacante para leer arbitrariamente memoria de otro contexto, por ejemplo, otro proceso.
ejemplo, en lugar de realizar límites verifique, la (s) rama (s) condicional (s) predicha (s)
Considere el caso donde el código en el Listado 1 es parte de un función (por ejemplo, una llamada
erróneamente podrían estar verificando un resultado de seguridad previamente calculado o un tipo
al sistema o una biblioteca) que recibe un mensaje sin firmar entero x de una fuente no confiable. El
de objeto Del mismo modo, el código que se ejecuta especulativamente puede tomar otras formas,
proceso que ejecuta el el código tiene acceso a una matriz de bytes sin firmar array1 de tamaño
como filtrar un resultado de comparación en un fijo ubicación de memoria o puede extenderse en
array1_size, y un segundo byte array array2 de tamaño 1 MB.
un número mucho mayor de instrucciones. El estado de caché descrito anteriormente también es
más restrictivo de lo que puede ser requerido. Por ejemplo, en algunos escenarios, el ataque
funciona incluso si se almacena en caché array1_size, por ejemplo, si los resultados de predicción de
rama se aplican durante la especulación ejecución incluso si los valores involucrados en la
El fragmento de código comienza con una verificación de límites en x que comparación son conocido. Dependiendo del procesador, ejecución especulativa
Es esencial para la seguridad. En particular, esta verificación evita que procesador de lectura de También puede iniciarse en una variedad de situaciones. Variantes adicionales se discuten en la
memoria sensible fuera de array1. Sección VI.
De lo contrario, una entrada x fuera de límites podría desencadenar una excepción o podría hacer
que el procesador acceda a memoria sensible suministrando x = (dirección de un byte secreto para A. Resultados experimentales
leer) - (base dirección de array1). Realizamos experimentos en múltiples arquitecturas de procesador x86, incluidos Intel Ivy Bridge
(i7-3630QM), Intel

3
Haswell (i7-4650U), Intel Broadwell (i7-5650U), Intel Skylake (Xeon no especificado en Google Cloud, El subsistema eBPF gestiona las estructuras de datos almacenadas en memoria del núcleo Los
i5-6200U, i7-6600U, i7-6700K), Intel Kaby Lake (i7-7660U) y AMD Ryzen. usuarios pueden solicitar la creación de estos datos estructuras, y luego se puede acceder a estas
La vulnerabilidad de Spectre se observó en todas estas CPU. estructuras de datos del código de bytes eBPF. Para hacer cumplir la seguridad de la memoria para
Se observaron resultados similares en los modos de 32 y 64 bits, y tanto Linux como Windows. estos operaciones, el núcleo almacena algunos metadatos asociados con cada una de esas
Algunos procesadores basados en el estructuras de datos y realiza comprobaciones contra este metadatos En particular, los metadatos
La arquitectura ARM también admite la ejecución especulativa [7], y nuestras pruebas iniciales en incluyen el tamaño de estructura de datos (que se establece una vez cuando la estructura de datos
un SoC Qualcomm Snapdragon 835 (con una CPU Qualcomm Kyro 280) y en un Samsung Exynos es creado y utilizado para evitar accesos fuera de límites) y el
7420 Octa SoC (con CPU Cortex-A57 y Cortex-A53) confirmado que estos procesadores ARM se ven Número de referencias de programas eBPF que se cargan en el núcleo El recuento de referencia
afectados. También observamos que la ejecución especulativa puede avanzar mucho antes de la rastrea cuántos eBPF se ejecutan programas que hacen referencia a la estructura de datos, lo que
instrucción puntero. En un Haswell i7-4650U, el código en el Apéndice C garantiza esa memoria que pertenece a la estructura de datos no se libera mientras están cargados,
(cf. Sección IV-B) funciona con hasta 188 instrucciones simples insertado en el código fuente entre los programas eBPF lo referencian.
la declaración "si" y la línea que accede a array1 / array2, que está justo debajo de Aumentamos la latencia de los controles de límites contra las longitudes de matrices administradas
192 microoperaciones que caben en el búfer de reordenamiento de este procesador por eBPF al abusar del intercambio falso. El núcleo almacena la longitud de la matriz y el recuento
(cf. Sección II-B). de referencias en el mismo línea de caché, lo que permite a un atacante mover la línea de caché que
contiene la longitud de la matriz en otro núcleo de CPU física en estado modificado (cf. [16, 53]).
B. Ejemplo de implementación en C Esto se hace cargando y descartar un programa eBPF que haga referencia al eBPF matriz en el otro
El Apéndice C incluye un código de prueba de concepto en C para x86 procesadores1 que sigue de núcleo físico, lo que hace que el núcleo aumentar y disminuir el contador de referencia de la matriz
cerca la descripción en en el otro núcleo físico Este ataque logra una tasa de fuga de aproximadamente 5000 B / s en una
Sección IV La implementación no optimizada puede leer CPU Haswell.
10 KB / s en un i7-4650U con una tasa de error baja (<0.01%). E. Precisión de los datos recuperados
Los ataques de espectro pueden revelar datos con alta precisión, pero errores
C. Ejemplo de implementación en JavaScript Puede surgir por varias razones. Pruebas para descubrir si un la ubicación de la memoria se almacena
Desarrollamos una prueba de concepto en JavaScript y la probamos en Google Chrome versión en caché, generalmente se usan mediciones de tiempo, cuya precisión puede ser limitada (como en
62.0.3202 que permite un sitio web para leer la memoria privada del proceso en el que se ejecuta. JavaScript o muchos
Los el código se ilustra en el Listado 2. Plataformas ARM). Como resultado, múltiples iteraciones de ataque pueden ser requerido para
En pases de entrenamiento incorrecto de predictores de rama, se establece el índice (a través de hacer una determinación confiable. Los errores también pueden se produce si los elementos de la
operaciones de bit) a un valor dentro del rango. En la iteración final, el índice se establece en una matriz2 se almacenan en caché de forma inesperada, por ejemplo, como resultado de la prefectura
dirección fuera de límites en de hardware, actividades del sistema operativo u otros procesos que acceden a la memoria (por
simpleByteArray. Utilizamos una variable localJunk para asegúrese de que las operaciones no estén ejemplo si array2 corresponde a la memoria en una biblioteca compartida que otros procesos están
optimizadas. De acuerdo a usando). Los atacantes pueden rehacer pases de ataque
ECMAScript 5.1 Sección 11.10 [13], la operación "| 0" convierte el valor en un entero de 32 bits, que dan como resultado que no haya elementos o más de 2 elementos en array2 en caché Pruebas
actuando como una pista de optimización para el intérprete de JavaScript. Como otro optimizado que utilizan este criterio de repetición simple (pero no otro corrección de errores) y una
Motores JavaScript, V8 realiza una compilación justo a tiempo para convierte JavaScript en lenguaje sincronización precisa basada en rdtscp producida tasas de error de aproximadamente 0.005% tanto
de máquina. Operaciones ficticias se colocaron en el código que rodea el Listado 2 para hacer en Intel Skylake como en Procesadores Kaby Lake.
simpleByteArray.length se almacena en la memoria local para que se puede eliminar del caché
durante el ataque. Ver
Listado 3 para la salida de desmontaje resultante de D8.
Dado que la instrucción clflush no es accesible desde
JavaScript, usamos el desalojo de caché en su lugar [27, 51], es decir, accedemos a otras ubicaciones
de memoria de tal manera que
Las ubicaciones de memoria de destino se desalojan después. Los los resultados filtrados se
transmiten a través del estado de caché de probeTable [n * 4096] para n ∈ 0..255, por lo que el
atacante tiene que desalojar estas 256 líneas de caché. El parámetro de longitud
(simpleByteArray.length en el código JavaScript y
[ebp-0xe0] en el desmontaje) necesita ser desalojado como bien. JavaScript no proporciona acceso
al rdtscp instrucción, y Chrome degrada intencionalmente la precisión de su temporizador de alta
resolución para disuadir ataques de tiempo usando
performance.now () [62]. Sin embargo, los trabajadores web
La función de HTML5 simplifica la creación de un hilo que disminuye repetidamente un valor en una
memoria compartida ubicación [24, 60]. Este enfoque produce un temporizador de alta resolución
eso proporciona suficiente resolución.

D. Implementación de ejemplo Explotando eBPF


Como tercer ejemplo de explotación de ramas condicionales, desarrollamos una prueba de concepto
confiable que pierde el núcleo memoria de un kernel de Linux no modificado sin parches contra
Spectre al abusar de la interfaz eBPF (BPF extendida).
eBPF es una interfaz de kernel de Linux basada en Berkeley
Filtro de paquetes (BPF) [49] que se puede utilizar para una variedad de propósitos, incluido el
filtrado de paquetes en función de su contenido.
eBPF permite a usuarios no privilegiados activar la interpretación o compilación JIT y posterior
ejecución de la proporcionada por el usuario, código de bytes eBPF verificado por el núcleo en el
contexto del núcleo.
El concepto básico del ataque es similar al concepto de
El ataque contra JavaScript.
En este ataque, usamos el código eBPF solo para el código ejecutado especulativamente. Usamos
código nativo en el espacio de usuario para adquirir la información del canal secreto. Esta es una
diferencia al ejemplo de JavaScript anterior, donde ambas funciones son implementado en el
lenguaje de script. Para acceder especulativamente ubicaciones dependientes del secreto en la
memoria del espacio del usuario, realizamos accesos especulativos de memoria fuera de límites a
una matriz en memoria del núcleo, con un índice lo suficientemente grande como para que el
espacio de usuario
Se accede a la memoria en su lugar. La prueba de concepto asume que el procesador de destino no
es compatible con el modo Supervisor
Prevención de acceso (SMAP). Sin embargo, los ataques sin esto
La suposición también es posible. Fue probado en un Intel Xeon
Haswell E5-1650 v3, en el que funciona tanto por defecto modo interpretado y el modo compilado
JIT no predeterminado de
eBPF. En una implementación altamente optimizada, podemos fugas de hasta 2000 B / s en esta
configuración. También fue probado en un
Procesador AMD PRO A8-9600 R7, en el que solo funciona en el modo compilado JIT no
predeterminado. Dejamos la investigación de razones para esto abierto para el trabajo futuro.
4

Вам также может понравиться