Unsorted Bin Attack
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
For more information about what is an unsorted bin check this page:
Bins & Memory AllocationsLas listas no ordenadas pueden escribir la dirección en unsorted_chunks (av)
en la dirección bk
del chunk. Por lo tanto, si un atacante puede modificar la dirección del puntero bk
en un chunk dentro del bin no ordenado, podría escribir esa dirección en una dirección arbitraria que podría ser útil para filtrar direcciones de Glibc o eludir alguna defensa.
Así que, 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).
Echando un vistazo al 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 chunk (para evitar Tcache) es posible ver que hoy en día el error malloc(): unsorted double linked list corrupted
se activa.
Por lo tanto, este ataque de bin no ordenado ahora (entre otras verificaciones) también requiere poder arreglar la lista doblemente enlazada para que se eluda 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 chunk falso en su posición fd
y que el fd
del chunk falso apunta a la arena.
Ten en cuenta que este ataque corrompe el bin no ordenado (por lo tanto, también pequeño y grande). Así que solo podemos usar asignaciones del fast bin ahora (un programa más complejo podría hacer otras asignaciones y fallar), y para activar 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 otras asignaciones hasta que se complete el exploit.
El código de guyinatuxedo lo explica muy bien, aunque si modificas los mallocs para asignar memoria lo suficientemente grande para no terminar en un Tcache puedes ver que el error mencionado anteriormente aparece impidiendo esta técnica: malloc(): unsorted double linked list corrupted
Este es en realidad un concepto muy básico. Los chunks en el bin no ordenado van a tener punteros. El primer chunk en el bin no ordenado tendrá en realidad los enlaces fd
y bk
apuntando a una parte de la arena principal (Glibc).
Por lo tanto, si puedes poner un chunk dentro de un bin no ordenado y leerlo (uso después de liberar) o asignarlo de nuevo sin sobrescribir al menos 1 de los punteros para luego leerlo, puedes tener una fuga de información de Glibc.
Un ataque similar utilizado en este informe, fue abusar de una estructura de 4 chunks (A, B, C y D - D es solo para evitar la consolidación con el chunk superior) así que se utilizó un desbordamiento de byte nulo en B para hacer que C indicara que B no estaba en uso. Además, en B se modificaron los datos de prev_size
para que el tamaño en lugar de ser el tamaño de B fuera A+B.
Luego se liberó C y se consolidó con A+B (pero B todavía estaba en uso). Se asignó un nuevo chunk de tamaño A y luego se escribieron las direcciones de libc filtradas en B desde donde fueron filtradas.
El objetivo es sobrescribir una variable global con un valor mayor que 4869 para que sea posible obtener la bandera y PIE no está habilitado.
Es posible generar chunks de tamaños arbitrarios y hay un desbordamiento de heap con el tamaño deseado.
El ataque comienza creando 3 chunks: chunk0 para abusar del desbordamiento, chunk1 para ser desbordado y chunk2 para que el chunk superior no consolide los anteriores.
Luego, chunk1 se libera y chunk0 se desborda para que el puntero bk
de chunk1 apunte a: bk = magic - 0x10
Luego, chunk3 se asigna con el mismo tamaño que chunk1, lo que activará el ataque de bin no ordenado y modificará el valor de la variable global, haciendo posible obtener la bandera.
La función de fusión es vulnerable porque si ambos índices pasados son el mismo, se reasignará sobre él y luego se liberará, pero devolviendo un puntero a esa región liberada que puede ser utilizada.
Por lo tanto, se crean 2 chunks: chunk0 que se fusionará consigo mismo y chunk1 para evitar la consolidación con el chunk superior. Luego, se llama a la función de fusión con chunk0 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 chunk de uso después de liberar), lo que filtrará una dirección de libc.
Como el binario tiene protecciones para solo malloc tamaños mayores que global_max_fast
, por lo que no se usa fastbin, se va a utilizar un ataque de 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, crear un nuevo chunk utilizará la dirección liberada previamente comprometida (0x20) que activará el ataque de bin no ordenado sobrescribiendo el global_max_fast
con un valor muy grande, permitiendo ahora crear chunks en fast bins.
Ahora se realiza un ataque de fast bin:
Primero se descubre que es posible trabajar con fast chunks 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 chunk 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 chunk de tamaño 0xfc
y se llama a la función de fusión con ese puntero dos veces, de esta manera obtenemos un puntero a un chunk liberado de tamaño 0xfc*2 = 0x1f8
en el fast bin.
Luego, se llama a la función de edición en este chunk para modificar la dirección fd
de este fast bin para que apunte a la función __free_hook
anterior.
Luego, se crea un chunk de tamaño 0x1f8
para recuperar del fast bin el chunk inútil anterior, por lo que se crea otro chunk de tamaño 0x1f8
para obtener un chunk de fast bin en el __free_hook
que se sobrescribe con la dirección de la función system
.
Y finalmente, se libera un chunk que contiene la cadena /bin/sh\x00
llamando a la función de eliminación, activando la función __free_hook
que apunta a system con /bin/sh\x00
como parámetro.
Otro ejemplo de abusar de un desbordamiento de 1B para consolidar chunks en el bin no ordenado y obtener una fuga de información de libc y luego realizar un ataque de fast bin para sobrescribir el gancho de malloc con una dirección de un gadget.
Solo podemos asignar chunks de tamaño mayor que 0x100
.
Sobrescribir global_max_fast
usando un ataque de bin no ordenado (funciona 1/16 veces debido a ASLR, porque necesitamos modificar 12 bits, pero debemos modificar 16 bits).
Ataque de Fast Bin para modificar un arreglo global de chunks. Esto proporciona una primitiva de lectura/escritura arbitraria, que permite modificar el GOT y hacer que algunas funciones apunten a system
.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)