Desbordamiento de Heap

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Información Básica

Un desbordamiento de heap es como un desbordamiento de pila pero en el heap. Básicamente significa que se reservó un espacio en el heap para almacenar algunos datos y los datos almacenados eran más grandes que el espacio reservado.

En los desbordamientos de pila sabemos que algunos registros como el puntero de instrucción o el marco de pila se van a restaurar desde la pila y podría ser posible abusar de esto. En el caso de los desbordamientos de heap, no hay información sensible almacenada por defecto en el bloque de heap que puede ser desbordado. Sin embargo, podría haber información sensible o punteros, por lo que la criticidad de esta vulnerabilidad depende de qué datos podrían ser sobrescritos y cómo un atacante podría abusar de esto.

Tip

Para encontrar los desplazamientos de desbordamiento, puedes usar los mismos patrones que en desbordamientos de pila.

Desbordamientos de Pila vs Desbordamientos de Heap

En los desbordamientos de pila, la disposición y los datos que van a estar presentes en la pila en el momento en que se puede activar la vulnerabilidad son bastante confiables. Esto se debe a que la pila es lineal, siempre aumentando en memoria colisionante, en lugares específicos de la ejecución del programa, la memoria de la pila generalmente almacena un tipo de datos similar y tiene una estructura específica con algunos punteros al final de la parte de la pila utilizada por cada función.

Sin embargo, en el caso de un desbordamiento de heap, la memoria utilizada no es lineal, sino que los bloques asignados suelen estar en posiciones separadas de la memoria (no uno al lado del otro) debido a bins y zonas que separan las asignaciones por tamaño y porque la memoria previamente liberada se utiliza antes de asignar nuevos bloques. Es complicado saber el objeto que va a colisionar con el que es vulnerable a un desbordamiento de heap. Por lo tanto, cuando se encuentra un desbordamiento de heap, es necesario encontrar una manera confiable de hacer que el objeto deseado esté al lado en memoria del que puede ser desbordado.

Una de las técnicas utilizadas para esto es Heap Grooming, que se utiliza, por ejemplo, en esta publicación. En la publicación se explica cómo, cuando en el kernel de iOS una zona se queda sin memoria para almacenar bloques de memoria, se expande por una página del kernel, y esta página se divide en bloques de los tamaños esperados que se utilizarían en orden (hasta la versión 9.2 de iOS, luego estos bloques se utilizan de manera aleatoria para dificultar la explotación de estos ataques).

Por lo tanto, en la publicación anterior donde ocurre un desbordamiento de heap, para forzar que el objeto desbordado colisione con un objeto víctima, se forzan varios kallocs por varios hilos para intentar asegurar que todos los bloques libres estén llenos y que se cree una nueva página.

Para forzar este llenado con objetos de un tamaño específico, la asignación fuera de línea asociada con un puerto mach de iOS es un candidato ideal. Al elaborar el tamaño del mensaje, es posible especificar exactamente el tamaño de la asignación kalloc y cuando el puerto mach correspondiente se destruye, la asignación correspondiente se liberará inmediatamente de nuevo a kfree.

Luego, algunos de estos marcadores de posición pueden ser liberados. La lista libre kalloc.4096 libera elementos en un orden de último en entrar, primero en salir, lo que básicamente significa que si algunos marcadores de posición son liberados y el exploit intenta asignar varios objetos víctima mientras intenta asignar el objeto vulnerable al desbordamiento, es probable que este objeto sea seguido por un objeto víctima.

Ejemplo libc

En esta página es posible encontrar una emulación básica de desbordamiento de heap que muestra cómo sobrescribir el bit de uso previo del siguiente bloque y la posición del tamaño previo es posible consolidar un bloque utilizado (haciéndolo pensar que es no utilizado) y luego asignarlo nuevamente pudiendo sobrescribir datos que se están utilizando en un puntero diferente también.

Otro ejemplo de protostar heap 0 muestra un ejemplo muy básico de un CTF donde un desbordamiento de heap puede ser abusado para llamar a la función ganadora para obtener la bandera.

En el ejemplo de protostar heap 1 es posible ver cómo abusando de un desbordamiento de búfer es posible sobrescribir en un bloque cercano una dirección donde se van a escribir datos arbitrarios del usuario.

Ejemplo ARM64

En la página https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/ puedes encontrar un ejemplo de desbordamiento de heap donde un comando que se va a ejecutar se almacena en el siguiente bloque del bloque desbordado. Así, es posible modificar el comando ejecutado sobrescribiéndolo con un exploit fácil como:

python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt

Otros ejemplos

  • Auth-or-out. Hack The Box
  • Usamos una vulnerabilidad de desbordamiento de enteros para obtener un desbordamiento de heap.
  • Corrompemos punteros a una función dentro de un struct del chunk desbordado para establecer una función como system y obtener ejecución de código.

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks