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:
- Si deseas ver tu empresa anunciada en HackTricks o descargar HackTricks en PDF ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Obtén la merchandising oficial de PEASS & HackTricks
- Descubre La Familia PEASS, nuestra colección exclusiva de NFTs
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte tus trucos de hacking enviando PRs a los repositorios de HackTricks y HackTricks Cloud en GitHub.
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 globalglobal_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 ap64(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 elglobal_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ño0xfc*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ño0x1f8
para obtener un fragmento del fast bin en el__free_hook
que se sobrescribe con la dirección de la funciónsystem
. - 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.