hacktricks/binary-exploitation/heap/unlink-attack.md

11 KiB

Attaque Unlink

Apprenez le piratage AWS de zéro à héros avec htARTE (Expert de l'équipe rouge AWS de HackTricks)!

Autres façons de soutenir HackTricks :

Informations de Base

Lorsque cette attaque a été découverte, elle permettait principalement un WWW (Write What Where), cependant, certaines vérifications ont été ajoutées rendant la nouvelle version de l'attaque plus intéressante mais plus complexe et inutile.

Exemple de Code:

Code ```c #include #include #include #include

// Altered from d778318b6a/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'attaque ne fonctionne pas si les tcaches sont utilisés (après 2.26)

### Objectif

Cette attaque permet de **changer un pointeur vers un chunk pour le faire pointer 3 adresses avant lui-même**. Si ce nouvel emplacement (alentours de l'endroit où se trouvait le pointeur) contient des éléments intéressants, comme d'autres allocations contrôlables / la pile..., il est possible de les lire/écraser pour causer un plus grand dommage.

* Si ce pointeur était situé dans la pile, car il pointe maintenant 3 adresses avant lui-même et que l'utilisateur peut potentiellement le lire et le modifier, il sera possible de divulguer des informations sensibles de la pile ou même de modifier l'adresse de retour (peut-être) sans toucher au canary
* Dans les exemples de CTF, ce pointeur est situé dans un tableau de pointeurs vers d'autres allocations, donc, en le faisant pointer 3 adresses avant et en étant capable de le lire et de l'écrire, il est possible de faire pointer les autres pointeurs vers d'autres adresses.\
Comme potentiellement l'utilisateur peut également lire/écrire les autres allocations, il peut divulguer des informations ou écraser de nouvelles adresses à des emplacements arbitraires (comme dans la GOT).

### Prérequis

* Un certain contrôle dans une mémoire (par exemple la pile) pour créer quelques chunks en donnant des valeurs à certaines des attributs.
* Fuite de pile pour définir les pointeurs du faux chunk.

### Attaque

* Il y a quelques chunks (chunk1 et chunk2)
* L'attaquant contrôle le contenu de chunk1 et les en-têtes de chunk2.
* Dans chunk1, l'attaquant crée la structure d'un faux chunk :
* Pour contourner les protections, il s'assure que le champ `size` est correct pour éviter l'erreur : `corrupted size vs. prev_size while consolidating`
* et les champs `fd` et `bk` du faux chunk pointent là où le pointeur de chunk1 est stocké avec des décalages de -3 et -2 respectivement, donc `fake_chunk->fd->bk` et `fake_chunk->bk->fd` pointent vers la position en mémoire (pile) où se trouve l'adresse réelle de 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>

* Les en-têtes du chunk2 sont modifiés pour indiquer que le chunk précédent n'est pas utilisé et que la taille est la taille du faux chunk contenu.
* Lorsque le deuxième chunk est libéré, ce faux chunk est désenchaîné se produisant :
* `fake_chunk->fd->bk` = `fake_chunk->bk`
* `fake_chunk->bk->fd` = `fake_chunk->fd`
* Auparavant, il a été fait en sorte que `fake_chunk->fd->bk` et `fake_chunk->fd->bk` pointent vers le même endroit (l'emplacement dans la pile où `chunk1` était stocké, donc c'était une liste chaînée valide). Comme **les deux pointent vers le même endroit**, seul le dernier (`fake_chunk->bk->fd = fake_chunk->fd`) aura **effet**.
* Cela va **écraser le pointeur vers chunk1 dans la pile vers l'adresse (ou les octets) stockés 3 adresses avant dans la pile**.
* Par conséquent, si un attaquant pouvait contrôler à nouveau le contenu du chunk1, il pourra **écrire dans la pile** en étant potentiellement capable d'écraser l'adresse de retour en sautant le canary et de modifier les valeurs et les points des variables locales. Même en modifiant à nouveau l'adresse de chunk1 stockée dans la pile vers un emplacement différent où si l'attaquant pouvait contrôler à nouveau le contenu de chunk1, il pourra écrire n'importe où.
* Notez que cela était possible car les **adresses sont stockées dans la pile**. Le risque et l'exploitation peuvent dépendre de **l'endroit où les adresses du faux chunk sont stockées**.

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

## Références

* [https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit)
* Bien qu'il soit étrange de trouver une attaque de désenchaînement même dans un CTF, voici quelques writeups où cette attaque a été utilisée :
* Exemple de CTF : [https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html)
* Dans cet exemple, au lieu de la pile, il y a un tableau d'adresses malloc'ées. L'attaque de désenchaînement est effectuée pour pouvoir allouer un chunk ici, permettant ainsi de contrôler les pointeurs du tableau d'adresses malloc'ées. Ensuite, il y a une autre fonctionnalité qui permet de modifier le contenu des chunks dans ces adresses, ce qui permet de pointer des adresses vers la GOT, de modifier les adresses de fonction pour obtenir des fuites de libc et RCE.
* Autre exemple de CTF : [https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html)
* Tout comme dans l'exemple précédent, il y a un tableau d'adresses d'allocations. Il est possible d'effectuer une attaque de désenchaînement pour faire pointer l'adresse de la première allocation quelques positions avant le début du tableau et d'écraser ensuite cette allocation à la nouvelle position. Par conséquent, il est possible d'écraser les pointeurs d'autres allocations pour pointer vers la GOT de atoi, l'imprimer pour obtenir une fuite de libc, puis écraser atoi GOT avec l'adresse d'un one gadget.
* Exemple de CTF avec des fonctions malloc et free personnalisées qui exploitent une vulnérabilité très similaire à l'attaque de désenchaînement : [https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html)
* Il y a un débordement qui permet de contrôler les pointeurs FD et BK du malloc personnalisé qui sera (personnalisé) libéré. De plus, le tas a le bit exec, il est donc possible de divulguer une adresse de tas et de pointer une fonction de la GOT vers un chunk de tas avec un shellcode à exécuter.

<details>

<summary><strong>Apprenez le piratage AWS de zéro à héros avec</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>

Autres façons de soutenir HackTricks :

* Si vous souhaitez voir votre **entreprise annoncée dans HackTricks** ou **télécharger HackTricks en PDF** Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Rejoignez** 💬 le [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez-nous** sur **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Partagez vos astuces de piratage en soumettant des PR aux** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.

</details>