Unsorted Bin Attack
Reading time: 12 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
Vir meer inligting oor wat 'n unsorted bin is, kyk hierdie bladsy:
Unsorted lists kan die adres na unsorted_chunks (av)
skryf in die bk
-adres van die chunk. Daarom, as 'n aanvaller die adres van die bk
-pointer in 'n chunk binne die unsorted bin kan wysig, kan hy daardie adres na 'n ewekansige adres skryf, wat nuttig kan wees om Glibc-adresse te leak of sekere verdediging te omseil.
Dus, basies laat hierdie aanval toe om 'n groot getal by 'n ewekansige adres te stel. Hierdie groot getal is 'n adres, wat 'n heap-adres of 'n Glibc-adres kan wees. 'n Tradisionele teiken was global_max_fast
om toe te laat dat fast bin bins met groter groottes geskep word (en van 'n unsorted bin attack na 'n fast bin attack oorgaan).
- Modern note (glibc â„ 2.39):
global_max_fast
het 'n 8âbit global geword. Om blindelings 'n pointer daarheen te skryf via 'n unsorted-bin write sal aangrensende libc-data beskadig en sal nie meer betroubaar die fastbin-limiet verhoog nie. Verkies ander teikens of primitiewe teen glibc 2.39+. Sien "Modern constraints" hieronder en oorweeg om te kombineer met ander tegnieke soos 'n large bin attack of 'n fast bin attack sodra jy 'n stabiele primitive het.
tip
Neem 'n kyk na die voorbeeld verskaf in https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle en deur 0x4000 en 0x5000 in plaas van 0x400 en 0x500 as chunk-groottes te gebruik (om Tcache te vermy) is dit moontlik om te sien dat deesdae die fout malloc(): unsorted double linked list corrupted
getrigger word.
Daarom vereis hierdie unsorted bin attack nou (benewens ander kontroles) ook dat die dubbel gekoppelde lys reggemaak kan word sodat hierdie fout omseil word â d.w.s. die kontrole victim->bk->fd == victim
of victim->fd == av (arena)
moet slaag. Dit beteken dat die adres waarheen ons wil skryf die adres van die vals chunk in sy fd
-posisie moet hĂȘ en dat die vals chunk se fd
na die arena wys.
[!CAUTION] Let wel dat hierdie aanval die unsorted bin korrupteer (en dus ook small en large). Ons kan nou slegs toewysings uit die fast bin gebruik (nie-'n meer komplekse program wat ander toewysings doen en kan crash nie), en om dit te trigger moet ons dieselfde grootte toewys â anders sal die program crash.
Let ook dat die oor-skrywing van global_max_fast
in hierdie geval kan help, aangesien die fast bin moontlik al die ander toewysings kan hanteer totdat die exploit voltooi is.
Die kode van guyinatuxedo verduidelik dit baie goed. As jy egter die mallocs aanpas om genoeg groot geheue te alokeer sodat dit nie in Tcache eindig nie, sal die voorheen genoemde fout verskyn en hierdie tegniek verhinder: malloc(): unsorted double linked list corrupted
Hoe die skryf werklik plaasvind
- Die unsorted-bin write word getrigger by
free
wanneer die vrygelaat chunk aan die kop van die unsorted list ingevoeg word. - Tydens invoeging voer die allocator uit:
bck = unsorted_chunks(av); fwd = bck->fd; victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;
- As jy
victim->bk
kan stel na(mchunkptr)(TARGET - 0x10)
voordat jyfree(victim)
aanroep, sal die finale stelling die skryf uitvoer:*(TARGET) = victim
. - Later, wanneer die allocator die unsorted bin verwerk, sal integriteitskontroles (onder andere) verifieer dat
bck->fd == victim
envictim->fd == unsorted_chunks(av)
voordat dit unlink. Omdat die invoeging reedsvictim
inbck->fd
(onsTARGET
) geskryf het, kan hierdie kontroles bevredig word as die skryf suksesvol was.
Moderne beperkings (glibc â„ 2.33)
Om unsortedâbin writes betroubaar op huidige glibc te gebruik:
- Tcache-interferensie: vir groottes wat in tcache val, word frees daarheen omgelei en raak nie die unsorted bin nie. Of:
- maak versoeke met groottes > MAX_TCACHE_SIZE (â„ 0x410 op 64âbit by verstek), of
- vul die ooreenstemmende tcache-bin (7 inskrywings) sodat addisionele frees by die globale bins uitkom, of
- as die omgewing beheerbaar is, deaktiveer tcache (bv. GLIBC_TUNABLES glibc.malloc.tcache_count=0).
- Integriteitskontroles op die unsorted list: op die volgende toewysingspad wat die unsorted bin ondersoek, kyk glibc (vereenvoudig):
bck->fd == victim
envictim->fd == unsorted_chunks(av)
; anders abort dit metmalloc(): unsorted double linked list corrupted
.
- Dit beteken dat die adres wat jy teiken twee skrywings moet verdra: eers
*(TARGET) = victim
tydens free; later, as die chunk verwyder word,*(TARGET) = unsorted_chunks(av)
(die allocator skryfbck->fd
terug na die binkop). Kies teikens waar die eenvoudige afdwing van 'n groot nieânul waarde nuttig is. - Tipiese stabiele teikens in moderne exploits:
- Aplikasie- of globale state wat "groot" waardes as vlae/limiete hanteer.
- Indirekte primitiewe (bv. opstel vir 'n daaropvolgende [fast bin attack](Fast Bin Attack) of om later 'n writeâwhatâwhere te pivot).
- Vermy
__malloc_hook
/__free_hook
op nuwe glibc: dit is verwyder in 2.34. Vermyglobal_max_fast
op â„ 2.39 (sien volgende noot).
- Oor
global_max_fast
op onlangse glibc:- Op glibc 2.39+ is
global_max_fast
'n 8âbit global. Die klassieke truuk om 'n heap-pointer daarin te skryf (om fastbins te vergroot) werk nie skoon nie en sal waarskynlik aangrensende allocator-state korrupteer. Verkies ander strategieĂ«.
- Op glibc 2.39+ is
Minimale exploitâresep (moderne glibc)
Doel: behaal 'n enkele ewekansige skryf van 'n heap-pointer na 'n ewekansige adres deur die unsortedâbin invoeg primitive te gebruik, sonder om te crash.
- Layout/grooming
- Alokeer A, B, C met groottes groot genoeg om tcache te omseil (bv. 0x5000). C verhoed konsolidasie met die top chunk.
- Korruptie
- Overflow van A in B se chunk header om
B->bk = (mchunkptr)(TARGET - 0x10)
te stel.
- Overflow van A in B se chunk header om
- Trigger
free(B)
. Tydens invoeging voer die allocatorbck->fd = B
uit, dus*(TARGET) = B
.
- Voortsetting
- As jy beplan om voort te gaan met toewysings en die program gebruik die unsorted bin, verwag dat die allocator later
*(TARGET) = unsorted_chunks(av)
sal stel. Beide waardes is tipies groot en kan genoeg wees om grootte-/limietâsemantiek in teikens te verander wat slegs vir "groot" nagaan.
- As jy beplan om voort te gaan met toewysings en die program gebruik die unsorted bin, verwag dat die allocator later
Pseudocode skeleton:
// 64-bit glibc 2.35â2.38 style layout (tcache bypass via large sizes)
void *A = malloc(0x5000);
void *B = malloc(0x5000);
void *C = malloc(0x5000); // guard
// overflow from A into Bâs metadata (prev_size/size/.../bk). You must control B->bk.
*(size_t *)((char*)B - 0x8) = (size_t)(TARGET - 0x10); // write fake bk
free(B); // triggers *(TARGET) = B (unsorted-bin insertion write)
note
âą As jy nie tcache met grootte kan omseil nie, vul die tcache bin vir die gekose grootte (7 frees) voordat jy die gecorrumpeerde chunk vrygee sodat die free na unsorted gaan.
âą As die program onmiddellik op die volgende allocation abort weens unsorted-bin checks, ondersoek weer dat victim->fd
steeds gelyk is aan die bin head en dat jou TARGET
die presiese victim
pointer hou na die eerste skryf.
Unsorted Bin Infoleak Attack
Dit is eintlik 'n baie basiese konsep. Die chunks in die unsorted bin sal pointere hĂȘ. Die eerste chunk in die unsorted bin sal eintlik die fd
en die bk
skakels hĂȘ wat na 'n deel van die main arena (Glibc) wys.
Dus, as jy 'n chunk in 'n unsorted bin kan plaas en dit kan lees (use after free) of dit weer kan allocate sonder om ten minste een van die pointere oor te skryf om dit daarna te lees, kan jy 'n Glibc info leak hĂȘ.
A similar attack used in this writeup, was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the prev_size
data was modified so the size instead of being the size of B was A+B.
Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked.
References & Other examples
- https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap
- Die doel is om 'n globale veranderlike oor te skryf met 'n waarde groter as 4869 sodat dit moontlik is om die flag te kry en PIE is nie aangeskakel nie.
- Dit is moontlik om chunks van arbitrĂȘre groottes te genereer en daar is 'n heap overflow met die gewenste grootte.
- Die aanval begin deur 3 chunks te skep: chunk0 om die overflow te misbruik, chunk1 wat oorvloed gaan word en chunk2 sodat die top chunk nie die vorige eenhede konsolideer nie.
- Dan word chunk1 vrygestel en chunk0 oorloop sodat die
bk
pointer van chunk1 wys na:bk = magic - 0x10
- Dan word chunk3 gealloceer met dieselfde grootte as chunk1, wat die unsorted bin attack sal aktiveer en die waarde van die globale veranderlike sal wysig, wat dit moontlik maak om die flag te kry.
- https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html
- Die merge-funksie is kwesbaar omdat as beide indekse wat deurgegee word dieselfde is, dit 'n realloc op dit sal uitvoer en dan vrygee, maar 'n pointer na daardie vrygestelde area sal teruggee wat gebruik kan word.
- Daarom word 2 chunks geskep: chunk0 wat met homself gemerg sal word en chunk1 om konsolidasie met die top chunk te voorkom. Dan word die merge function met chunk0 twee keer geroep wat 'n use after free sal veroorsaak.
- Dan word die
view
function met indeks 2 geroep (wat die indeks van die use after free chunk is), wat 'n libc address sal leak. - Aangesien die binary beskermings het om slegs sizes groter as
global_max_fast
te malloc, sodat geen fastbin gebruik word nie, gaan 'n unsorted bin attack gebruik word om die globale veranderlikeglobal_max_fast
oor te skryf. - Dan is dit moontlik om die edit function met indeks 2 (die use after free pointer) te roep en die
bk
pointer oor te skryf om nap64(global_max_fast-0x10)
te wys. Daarna sal die skep van 'n nuwe chunk die voorheen gekompromitteerde vryadres (0x20) gebruik en die unsorted bin attack sal getrigger word wat dieglobal_max_fast
oorskryf met 'n baie groot waarde, wat nou toelaat om chunks in fast bins te skep. - Nou word 'n fast bin attack uitgevoer:
- Eerstens is dit ontdek dat dit moontlik is om met fast chunks of size 200 in die
__free_hook
ligging te werk: gef†p &__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef†x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
- As ons daarin slaag om 'n fast chunk van grootte 0x200 in hierdie ligging te kry, sal dit moontlik wees om 'n function pointer oor te skryf wat uitgevoer sal word.
- Daarvoor word 'n nuwe chunk van grootte
0xfc
geskep en die merged function met daardie pointer twee keer geroep; op hierdie manier verkry ons 'n pointer na 'n vrygestelde chunk van grootte0xfc*2 = 0x1f8
in die fast bin. - Dan word die edit function op hierdie chunk geroep om die
fd
adres van hierdie fast bin te wysig om na die vorige__free_hook
funksie te wys. - Daarna word 'n chunk van grootte
0x1f8
geskep om uit die fast bin die vorige nuttelose chunk te herwin, sodat nog 'n chunk van grootte0x1f8
geskep word om 'n fast bin chunk in die__free_hook
te kry, wat met die adres van diesystem
funksie oorskryf word. - En uiteindelik word 'n chunk wat die string
/bin/sh\x00
bevat vrygestel deur die delete function te roep, wat die__free_hook
funksie aktiveer wat na system wys met/bin/sh\x00
as parameter. - CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
- 'n Ander voorbeeld van die misbruik van 'n 1B overflow om chunks in die unsorted bin te konsolideer en 'n libc infoleak te kry en dan 'n fast bin attack uit te voer om die malloc hook met 'n one gadget address oorskryf.
- Robot Factory. BlackHat MEA CTF 2022
- Ons kan slegs chunks van grootte groter as
0x100
alloceer. - Oorskryf
global_max_fast
met 'n Unsorted Bin attack (werk 1/16 keer as gevolg van ASLR, omdat ons 12 bisse moet wysig, maar ons moet 16 bisse wysig). - Fast Bin attack om 'n globale array van chunks te wysig. Dit gee 'n arbitrary read/write primitive, wat toelaat om die GOT te wysig en 'n funksie te stel om na
system
te wys.
References
- Glibc malloc unsorted-bin integriteitskontroles (voorbeeld in 2.33 bron): https://elixir.bootlin.com/glibc/glibc-2.33/source/malloc/malloc.c
global_max_fast
en verwante definisies in moderne glibc (2.39): https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.