Off by one overflow
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Informazioni di base
Avere accesso a un 1B overflow permette a un attacker di modificare il campo size del chunk successivo. Questo consente di manomettere quali chunk vengono effettivamente freed, potenzialmente generando un chunk che contiene un altro chunk legittimo. L’exploitation è simile a double free o a chunk sovrapposti.
Esistono 2 tipi di vulnerabilità off by one:
- Byte arbitrario: Questo tipo permette di sovrascrivere quel byte con qualsiasi valore
- Null byte (off-by-null): Questo tipo permette di sovrascrivere quel byte solo con 0x00
- Un esempio comune di questa vulnerabilità può essere visto nel seguente codice dove il comportamento di
strlenestrcpyè inconsistente, il che permette di impostare un byte 0x00 all’inizio del chunk successivo. - Questo può essere sfruttato con la House of Einherjar.
- Se si usa Tcache, questo può essere sfruttato per ottenere una situazione di double free.
Off-by-null
```c // From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/ int main(void) { char buffer[40]=""; void *chunk1; chunk1 = malloc(24); puts("Get Input"); gets(buffer); if(strlen(buffer)==24) { strcpy(chunk1,buffer); } return 0; } ```Tra gli altri controlli, ora ogni volta che un chunk è free il previous size viene confrontato con la size configurata nel chunk dei metadata, rendendo questo attacco piuttosto complesso a partire dalla versione 2.28.
Esempio di codice:
- https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c
- Questo attacco non funziona più a causa dell’uso di Tcaches.
- Inoltre, se provi ad abusarne usando chunk più grandi (quindi tcaches non sono coinvolti), otterrai l’errore:
malloc(): invalid next size (unsorted)
Obiettivo
- Fare in modo che un chunk sia contenuto all’interno di un altro chunk in modo che scrivendo sul secondo chunk si possa sovrascrivere quello contenuto
Requisiti
- Off by one overflow per modificare le informazioni dei metadata della size
General off-by-one attack
- Allocate three chunks
A,BandC(say sizes 0x20), and another one to prevent consolidation with the top-chunk. - Free
C(inserted into 0x20 Tcache free-list). - Use chunk
Ato overflow onB. Abuse off-by-one to modify thesizefield ofBfrom 0x21 to 0x41. - Now we have
Bcontaining the free chunkC - Free
Band allocate a 0x40 chunk (it will be placed here again) - We can modify the
fdpointer fromC, which is still free (Tcache poisoning)
Off-by-null attack
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that it’s 0x10 smaller than it really is).
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as
b + b->sizenever updates the c chunk because the pointed address is smaller than it should. - Then, b1 and c gets freed. As
c - c->prev_sizestill points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c. - Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2.
This image explains perfectly the attack:
.png)
https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
Note sul hardening & bypass di glibc moderno (>=2.32)
- Safe-Linking ora protegge ogni puntatore della singly linked bin memorizzando
fd = ptr ^ (chunk_addr >> 12), quindi un off-by-one che modifica solo il byte basso dellasizedi solito richiede anche un heap leak per ricalcolare la maschera XOR prima che il Tcache poisoning funzioni. - Un pratico leakless trick è “double-protect” un puntatore: codifica un puntatore che già controlli con
PROTECT_PTR, poi riutilizza lo stesso gadget per codificare il puntatore falsificato in modo che il controllo di allineamento passi senza rivelare nuovi indirizzi. - Workflow for Safe-Linking + single-byte corruptions:
- Grow the victim chunk until it fully covers a freed chunk you already control (overlapping-chunk setup).
- Leak any heap pointer (stdout, UAF, partially controlled struct) and derive the key
heap_base >> 12. - Re-encode free-list pointers before writing them—stage the encoded value inside user data and memcpy it later if you only own single-byte writes.
- Combine with Tcache bin attacks to redirect allocations into
__free_hookortcache_perthread_structentries once the forged pointer is properly encoded.
Un helper minimale per esercitarsi nel passaggio di encode/decode durante il debug di exploit moderni:
def protect(ptr, chunk_addr):
return ptr ^ (chunk_addr >> 12)
def reveal(encoded, chunk_addr):
return encoded ^ (chunk_addr >> 12)
chunk = 0x55555555c2c0
encoded_fd = protect(0xdeadbeefcaf0, chunk)
print(hex(reveal(encoded_fd, chunk))) # 0xdeadbeefcaf0
Obiettivo reale recente: glibc __vsyslog_internal off-by-one (CVE-2023-6779)
- Nel gennaio 2024 Qualys ha descritto CVE-2023-6779, un off-by-one in
__vsyslog_internal()che si attiva quando le stringhe di formato disyslog()/vsyslog()superanoINT_MAX, quindi il terminatore\0corrompe il byte meno significativo del camposizedel chunk successivo su sistemi glibc 2.37–2.39 (Qualys advisory). - La loro pipeline di exploit su Fedora 38:
- Costruire un ident troppo lungo per
openlog()in modo chevasprintfritorni un buffer heap accanto a dati controllati dall’attaccante. - Chiamare
syslog()per corrompere il bytesize | prev_inusedel chunk vicino, fare free su quel chunk e forzare la consolidazione che sovrappone i dati controllati dall’attaccante. - Usare la vista sovrapposta per corrompere i metadata di
tcache_perthread_structe indirizzare la successiva allocazione verso__free_hook, sovrascrivendolo consystem/un one_gadget per root.
- Per riprodurre la scrittura corruttrice in un harness, eseguire un fork con un
argv[0]gigantesco, chiamareopenlog(NULL, LOG_PID, LOG_USER)e poisyslog(LOG_INFO, "%s", payload)dovepayload = b"A" * 0x7fffffff; iheap binsdipwndbgmostrano immediatamente la sovrascrittura di un singolo byte. - Ubuntu traccia il bug come CVE-2023-6779, documentando la stessa troncatura a INT che rende questo un primitivo off-by-one affidabile.
Altri esempi e riferimenti
- https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
- Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
- Off-by-one dovuto a
strlenche considera il camposizedel chunk successivo. - Viene usato Tcache, quindi un attacco off-by-one generale funziona per ottenere un primitivo di arbitrary write tramite Tcache poisoning.
- Asis CTF 2016 b00ks
- È possibile abusare di un off-by-one per ottenere un leak di un indirizzo dall’heap perché il byte 0x00 alla fine di una stringa viene sovrascritto dal campo successivo.
- L’arbitrary write si ottiene sfruttando la scrittura off-by-one per far puntare il puntatore in un’altra posizione dove verrà costruita una fake struct con puntatori falsi. Poi è possibile seguire il puntatore di questa struct per ottenere arbitrary write.
- L’indirizzo di libc viene leakato perché se l’heap è esteso tramite mmap, la memoria allocata da mmap ha un offset fisso rispetto a libc.
- Infine l’arbitrary write viene sfruttato per scrivere nell’indirizzo di
__free_hookcon un one gadget. - plaidctf 2015 plaiddb
- C’è una vulnerabilità NULL off-by-one nella funzione
getlineche legge le linee di input utente. Questa funzione viene usata per leggere la “key” del contenuto e non il contenuto. - Nel writeup vengono creati 5 chunk iniziali:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) per evitare la consolidazione con il top chunk
- Poi i chunk 1, 5 e 3 vengono liberati, quindi:
-
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- Poi, abusando di chunk3 (0x1f8) il null off-by-one viene sfruttato per scrivere il prev_size a `0x4e0`.
- Nota come le dimensioni dei chunk inizialmente allocati 1, 2, 5 e 3 più gli header di 4 di questi chunk equivalgono a `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Poi il chunk 4 viene liberato, generando un chunk che consuma tutti i chunk fino all'inizio:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- Poi vengono allocati `0x200` bytes riempiendo il chunk originale 1
- E altri 0x200 byte vengono allocati, distruggendo chunk2; quindi non c'è alcun fucking leak e questo non funziona — forse non si doveva fare
- Poi alloca un altro chunk con 0x58 "a" (sovrascrivendo chunk2 e raggiungendo chunk5) e modifica il `fd` del fast bin chunk di chunk5 puntandolo a `__malloc_hook`
- Poi viene allocato un chunk di 0x68 in modo che il fake fast bin chunk in `__malloc_hook` sia il fast bin chunk successivo
- Infine viene allocato un nuovo fast bin chunk di 0x68 e `__malloc_hook` viene sovrascritto con l'indirizzo di un `one_gadget`
## Riferimenti
- [Qualys Security Advisory – CVE-2023-6246/6779/6780](https://www.qualys.com/2024/01/30/cve-2023-6246/syslog.txt)
- [Ubuntu Security – CVE-2023-6779](https://ubuntu.com/security/CVE-2023-6779)
- [Breaking Safe-Linking in Modern Glibc – Google CTF 2022 "saas" analysis](https://blog.csdn.net/2402_86373248/article/details/148717274)
> [!TIP]
> Impara e pratica il hacking AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Impara e pratica il hacking GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Impara e pratica il hacking Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Supporta HackTricks</summary>
>
> - Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
> - **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos github.
>
> </details>
HackTricks

