hacktricks/binary-exploitation/heap/unsorted-bin-attack.md

8.7 KiB

Ataque al Bin No Ordenado

Aprende hacking en AWS de cero a héroe con htARTE (Experto en Equipos Rojos de AWS de HackTricks)!

Otras formas de apoyar a HackTricks:

Información Básica

Para obtener más información sobre qué es un bin no ordenado, consulta esta página:

{% content-ref url="bins-and-memory-allocations.md" %} bins-and-memory-allocations.md {% endcontent-ref %}

Las 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 ser capaz de escribir esa dirección en una dirección arbitraria que podría ser útil para filtrar direcciones de libc o evitar alguna defensa.

Por lo tanto, básicamente, este ataque permite sobrescribir alguna dirección arbitraria con un número grande (una dirección que podría ser una dirección de heap o de libc) como alguna dirección de stack que podría ser filtrada o alguna restricción como la variable global global_max_fast para permitir crear bins rápidos con tamaños más grandes (y pasar de un ataque al bin no ordenado a un ataque al bin rápido).

{% hint style="success" %} 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 chunk (para evitar tcaches), es posible ver que actualmente se desencadena el error malloc(): unsorted double linked list corrupted.

Por lo tanto, este ataque al bin no ordenado ahora (entre otras comprobaciones) también requiere poder arreglar la lista doble enlazada para que se salte victim->bck->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. {% endhint %}

{% hint style="danger" %} 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 bin rápido (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 hacer global_max_fast podría ayudar en este caso confiando en que el bin rápido podrá encargarse de todas las demás asignaciones hasta que se complete el exploit. {% endhint %}

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, verás que aparece el error mencionado anteriormente que evita esta técnica: malloc(): unsorted double linked list corrupted

Ataque de Fuga de Información del Bin No Ordenado

Este es en realidad un concepto muy básico. Los chunks en el bin no ordenado tendrán punteros dobles para crear el bin. El primer chunk en el bin no ordenado realmente tendrá los enlaces FD y BK apuntando a una parte de la arena principal (libc).
Por lo tanto, si puedes colocar un chunk 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 libc.

Referencias y Otros Ejemplos

  • https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap
  • El objetivo es sobrescribir una variable global con un valor mayor a 4869 para poder obtener la bandera y sin habilitar PIE.
  • 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, se libera chunk1 y se desborda chunk0 para que el puntero bk de chunk1 apunte a: bk = magic - 0x10
  • Luego, se asigna chunk3 con el mismo tamaño que chunk1, lo que desencadenará el ataque al bin no ordenado y modificará el valor de la variable global, permitiendo obtener la bandera.
  • https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html
  • 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 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 asignar solo tamaños mayores que global_max_fast para que no se use un 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 edit 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 chunk, 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 chunks en los bins rápidos.
  • Ahora se realiza un ataque al bin rápido:
  • En primer lugar, se descubre que es posible trabajar con chunks rápidos de tamaño 200 en la ubicación de __free_hook:
  • gef➤  p &__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 de edición 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 del 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 de eliminación, desencadenando la función __free_hook que apunta a system con /bin/sh\x00 como parámetro.