Memory Tagging Extension (MTE)

Aprende hacking en AWS desde cero hasta experto con htARTE (Experto en Equipos Rojos de AWS de HackTricks)!

Otras formas de apoyar a HackTricks:

Información Básica

La Extensión de Etiquetado de Memoria (MTE) está diseñada para mejorar la confiabilidad y seguridad del software mediante la detección y prevención de errores relacionados con la memoria, como desbordamientos de búfer y vulnerabilidades de uso después de liberar. MTE, como parte de la arquitectura ARM, proporciona un mecanismo para adjuntar una pequeña etiqueta a cada asignación de memoria y una etiqueta correspondiente a cada puntero que referencia esa memoria. Este enfoque permite la detección de accesos a memoria ilegales en tiempo de ejecución, reduciendo significativamente el riesgo de explotar dichas vulnerabilidades para ejecutar código arbitrario.

Cómo Funciona la Extensión de Etiquetado de Memoria

MTE opera mediante la división de la memoria en bloques pequeños de tamaño fijo, con cada bloque asignado una etiqueta, típicamente de unos pocos bits de tamaño.

Cuando se crea un puntero para apuntar a esa memoria, obtiene la misma etiqueta. Esta etiqueta se almacena en los bits no utilizados de un puntero de memoria, vinculando efectivamente el puntero a su bloque de memoria correspondiente.

Cuando un programa accede a la memoria a través de un puntero, el hardware MTE verifica que la etiqueta del puntero coincida con la etiqueta del bloque de memoria. Si las etiquetas no coinciden, indica un acceso a memoria ilegal.

Etiquetas de Punteros MTE

Las etiquetas dentro de un puntero se almacenan en 4 bits dentro del byte superior:

Por lo tanto, esto permite hasta 16 valores de etiqueta diferentes.

Etiquetas de Memoria MTE

Cada 16B de memoria física tiene una etiqueta de memoria correspondiente.

Las etiquetas de memoria se almacenan en una región de RAM dedicada (no accesible para uso normal). Teniendo etiquetas de 4 bits para cada 16B de etiquetas de memoria, hasta un 3% de la RAM.

ARM introduce las siguientes instrucciones para manipular estas etiquetas en la memoria RAM dedicada:

STG [<Xn/SP>], #<simm>    Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>]       Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP>      Insert Random [pointer] Tag
...

Modos de Verificación

Síncrono

La CPU verifica las etiquetas durante la ejecución de la instrucción, si hay una discrepancia, genera una excepción. Este es el más lento y seguro.

Asíncrono

La CPU verifica las etiquetas asincrónicamente, y cuando se encuentra una discrepancia, establece un bit de excepción en uno de los registros del sistema. Es más rápido que el anterior pero es incapaz de señalar la instrucción exacta que causó la discrepancia y no genera la excepción de inmediato, dando tiempo al atacante para completar su ataque.

Mixto

???

Ejemplos de Implementación y Detección

Llamado KASAN basado en etiquetas de hardware, KASAN basado en MTE o MTE en el kernel. Los asignadores de memoria del kernel (como kmalloc) llamarán a este módulo que preparará la etiqueta a utilizar (aleatoriamente), la adjuntará al espacio de kernel asignado y al puntero devuelto.

Ten en cuenta que solo marcará suficientes gránulos de memoria (16B cada uno) para el tamaño solicitado. Entonces, si el tamaño solicitado fue 35 y se dio un bloque de 60B, marcará los primeros 16*3 = 48B con esta etiqueta y el resto se marcará con una llamada etiqueta inválida (0xE).

La etiqueta 0xF es el puntero de coincidencia total. Una memoria con este puntero permite que se utilice cualquier etiqueta para acceder a su memoria (sin discrepancias). Esto podría evitar que MTE detecte un ataque si esta etiqueta se está utilizando en la memoria atacada.

Por lo tanto, solo hay 14 valores que se pueden usar para generar etiquetas, ya que 0xE y 0xF están reservados, lo que da una probabilidad de reutilización de etiquetas de 1/17 -> alrededor del 7%.

Si el kernel accede al gránulo de etiqueta inválida, se detectará la discrepancia. Si accede a otra ubicación de memoria, si la memoria tiene una etiqueta diferente (o la etiqueta inválida), se detectará la discrepancia. Si el atacante tiene suerte y la memoria está utilizando la misma etiqueta, no se detectará. Las posibilidades son alrededor del 7%.

Otro error ocurre en el último gránulo de la memoria asignada. Si la aplicación solicitó 35B, se le dio el gránulo del 32 al 48. Por lo tanto, los bytes del 36 al 47 están utilizando la misma etiqueta pero no fueron solicitados. Si el atacante accede a estos bytes adicionales, esto no se detecta.

Cuando se ejecuta kfree(), la memoria se etiqueta nuevamente con la etiqueta de memoria inválida, por lo que en un uso después de liberar, cuando se accede nuevamente a la memoria, se detecta la discrepancia.

Sin embargo, en un uso después de liberar, si el mismo bloque se vuelve a asignar con la MISMA etiqueta que anteriormente, un atacante podrá utilizar este acceso y esto no se detectará (alrededor del 7% de probabilidad).

Además, solo slab y page_alloc utilizan memoria etiquetada, pero en el futuro esto también se utilizará en vmalloc, stack y globals (en el momento del video, estos aún pueden ser abusados).

Cuando se detecta una discrepancia, el kernel entrará en pánico para evitar una mayor explotación y reintentos del exploit (MTE no tiene falsos positivos).

Referencias

Aprende a hackear AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Última actualización