Unsorted Bin Attack
Last updated
Last updated
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)
Para obtener más información sobre qué es un bin no ordenado, consulta esta página:
Bins & Memory AllocationsLas listas no ordenadas pueden escribir la dirección en unsorted_chunks (av)
en la dirección bk
del fragmento. Por lo tanto, si un atacante puede modificar la dirección del puntero bk
en un fragmento dentro del bin no ordenado, podría ser capaz de escribir esa dirección en una dirección arbitraria que podría ser útil para filtrar direcciones de Glibc o evitar alguna defensa.
Por lo tanto, básicamente, este ataque permite establecer un número grande en una dirección arbitraria. Este número grande es una dirección, que podría ser una dirección de heap o una dirección de Glibc. Un objetivo típico es global_max_fast
para permitir crear bins de fast bin con tamaños más grandes (y pasar de un ataque de bin no ordenado a un ataque de fast bin).
Al observar el ejemplo proporcionado en https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle y usando 0x4000 y 0x5000 en lugar de 0x400 y 0x500 como tamaños de fragmento (para evitar Tcache), es posible ver que en la actualidad se desencadena el error malloc(): unsorted double linked list corrupted
.
Por lo tanto, este ataque de bin no ordenado ahora (entre otras comprobaciones) también requiere poder arreglar la lista doble enlazada para que se salte esto victim->bk->fd == victim
o no victim->fd == av (arena)
, lo que significa que la dirección donde queremos escribir debe tener la dirección del fragmento falso en su posición fd
y que el fd
del fragmento falso apunta a la arena.
Ten en cuenta que este ataque corrompe el bin no ordenado (por lo tanto, también el pequeño y el grande). Por lo tanto, ahora solo podemos utilizar asignaciones del fast bin (un programa más complejo podría hacer otras asignaciones y fallar), y para desencadenar esto debemos asignar el mismo tamaño o el programa fallará.
Ten en cuenta que sobrescribir global_max_fast
podría ayudar en este caso confiando en que el fast bin podrá encargarse de todas las demás asignaciones hasta que se complete el exploit.
El código de guyinatuxedo lo explica muy bien, aunque si modificas las asignaciones de memoria para asignar memoria lo suficientemente grande para que no termine en un Tcache, puedes ver que aparece el error mencionado anteriormente que evita esta técnica: malloc(): unsorted double linked list corrupted
Este es en realidad un concepto muy básico. Los fragmentos en el bin no ordenado van a tener punteros. El primer fragmento en el bin no ordenado realmente tendrá los enlaces fd
y bk
apuntando a una parte de la arena principal (Glibc).
Por lo tanto, si puedes colocar un fragmento dentro de un bin no ordenado y leerlo (uso después de liberar) o asignarlo nuevamente sin sobrescribir al menos 1 de los punteros para luego leerlo, puedes obtener una fuga de información de Glibc.
Un ataque similar utilizado en este informe, consistió en abusar de una estructura de 4 fragmentos (A, B, C y D - D es solo para evitar la consolidación con el fragmento superior) por lo que se utilizó un desbordamiento de byte nulo en B para hacer que C indicara que B no se estaba utilizando. Además, en B se modificó los datos de prev_size
para que el tamaño en lugar de ser el tamaño de B fuera A+B.
Luego se desasignó C y se consolidó con A+B (pero B aún estaba en uso). Se asignó un nuevo fragmento de tamaño A y luego se escribieron las direcciones filtradas de Glibc en B desde donde se filtraron.
El objetivo es sobrescribir una variable global con un valor mayor que 4869 para poder obtener la bandera y PIE no está habilitado.
Es posible generar fragmentos de tamaños arbitrarios y hay un desbordamiento de heap con el tamaño deseado.
El ataque comienza creando 3 fragmentos: fragmento0 para abusar del desbordamiento, fragmento1 para ser desbordado y fragmento2 para que el fragmento superior no consolide los anteriores.
Luego, se libera el fragmento1 y se desborda el fragmento0 para que el puntero bk
del fragmento1 apunte a: bk = magic - 0x10
Luego, se asigna el fragmento3 con el mismo tamaño que el fragmento1, lo que desencadenará el ataque al bin no ordenado y modificará el valor de la variable global, lo que hace posible obtener la bandera.
La función de fusión es vulnerable porque si ambos índices pasados son iguales, se realocará en él y luego se liberará, pero devolviendo un puntero a esa región liberada que se puede utilizar.
Por lo tanto, se crean 2 fragmentos: fragmento0 que se fusionará consigo mismo y fragmento1 para evitar la consolidación con el fragmento superior. Luego, se llama a la función de fusión con el fragmento0 dos veces, lo que causará un uso después de liberar.
Luego, se llama a la función view
con el índice 2 (que es el índice del fragmento de uso después de liberar), lo que filtrará una dirección de Glibc.
Como el binario tiene protecciones para asignar solo tamaños mayores que global_max_fast
para que no se use fastbin, se utilizará un ataque al bin no ordenado para sobrescribir la variable global global_max_fast
.
Luego, es posible llamar a la función de edición con el índice 2 (el puntero de uso después de liberar) y sobrescribir el puntero bk
para que apunte a p64(global_max_fast-0x10)
. Luego, al crear un nuevo fragmento, se usará la dirección de liberación comprometida anteriormente (0x20) y se desencadenará el ataque al bin no ordenado sobrescribiendo el global_max_fast
con un valor muy grande, lo que ahora permite crear fragmentos en los bins rápidos.
Ahora se realiza un ataque al fast bin:
En primer lugar, se descubre que es posible trabajar con fragmentos rápidos de tamaño 200 en la ubicación de __free_hook
:
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
Si logramos obtener un fragmento rápido de tamaño 0x200 en esta ubicación, será posible sobrescribir un puntero de función que se ejecutará.
Para esto, se crea un nuevo fragmento de tamaño 0xfc
y se llama a la función fusionada con ese puntero dos veces, de esta manera obtenemos un puntero a un fragmento liberado de tamaño 0xfc*2 = 0x1f8
en el fast bin.
Luego, se llama a la función edit en este fragmento para modificar la dirección fd
de este fast bin para que apunte a la función __free_hook
anterior.
Luego, se crea un fragmento con tamaño 0x1f8
para recuperar del fast bin el fragmento inútil anterior, por lo que se crea otro fragmento de tamaño 0x1f8
para obtener un fragmento de fast bin en el __free_hook
que se sobrescribe con la dirección de la función system
.
Y finalmente se libera un fragmento que contiene la cadena /bin/sh\x00
llamando a la función delete, desencadenando la función __free_hook
que apunta a system con /bin/sh\x00
como parámetro.
Otro ejemplo de abuso de un desbordamiento de 1B para consolidar fragmentos en el unsorted bin y obtener una fuga de información de libc y luego realizar un ataque de fast bin para sobrescribir el gancho de asignación con una dirección de un solo gadget
Solo podemos asignar fragmentos de tamaño mayor que 0x100
.
Sobrescribir global_max_fast
usando un ataque Unsorted Bin (funciona 1/16 veces debido a ASLR, porque necesitamos modificar 12 bits, pero debemos modificar 16 bits).
Ataque de Fast Bin para modificar una matriz global de fragmentos. Esto proporciona un primitivo de lectura/escritura arbitrario, lo que permite modificar la GOT y hacer que alguna función apunte a system
.
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)