Off by one overflow
Tip
AWS Hacking’i öğrenin ve pratik yapın:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın:HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking’i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Temel Bilgi
Sadece bir 1B overflow erişimine sahip olmak, saldırganın sonraki chunk’ın size alanını değiştirmesine olanak verir. Bu, hangi chunk’ların gerçekten freed edildiği üzerinde oynama yapılmasına izin vererek, potansiyel olarak başka bir geçerli chunk içeren bir chunk oluşturabilir. Sömürme, double free veya overlapping chunks’a benzer.
Off by one zafiyetlerinin 2 türü vardır:
- Arbitrary byte: Bu tür, ilgili baytı herhangi bir değerle üzerine yazmaya izin verir
- Null byte (off-by-null): Bu tür, o baytı sadece 0x00 ile üzerine yazmaya izin verir
- Bu zafiyetin yaygın bir örneği aşağıdaki kodda görülebilir; burada
strlenvestrcpy’nin davranışları tutarsızdır ve bu, sonraki chunk’ın başına 0x00 yazılmasına izin verir. - Bu, House of Einherjar ile sömürülebilir.
- Tcache kullanılıyorsa, bu bir double free durumuna yol açabilir.
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; } ```Diğer kontrollerin yanı sıra, artık bir chunk free olduğunda previous size metadata’daki chunk ile karşılaştırılıyor; bu nedenle bu saldırı version 2.28’den itibaren oldukça karmaşık hale geldi.
Code example:
- https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c
- This attack is no longer working due to the use of Tcaches.
- Moreover, if you try to abuse it using larger chunks (so tcaches aren’t involved), you will get the error:
malloc(): invalid next size (unsorted)
Goal
- Bir chunk’ın başka bir chunk içinde yer almasını sağlamak; böylece ikinci chunk üzerinde yazma erişimi, içindeki chunk’ı overwrite etmeye izin verir
Requirements
- Off by one overflow ile size metadata bilgisini değiştirmek
General off-by-one attack
- Üç chunk ayırın:
A,BveC(ör. size 0x20), ayrıca top-chunk ile birleşmeyi önlemek için başka bir chunk daha. C’yi free edin (0x20 Tcache free-list içine yerleştirilecek).Achunk’ını kullanarakBüzerinde overflow yapın. Off-by-one ileB’ninsizealanını 0x21’den 0x41’e değiştirin.- Artık
Biçinde free olanCchunk’ı bulunuyor. B’yi free edin ve 0x40 boyutunda bir chunk allocate edin (buraya yerleştirilecektir).- Hâlâ free olan
C’ninfdpointer’ını değiştirebiliriz (Tcache poisoning).
Off-by-null attack
- Ardışık olarak yer ayrılmış 3 memory chunk’ı (a, b, c) var. Ortadaki free ediliyor. İlk chunk off by one overflow açığı içeriyor ve attacker bunu 0x00 ile suiistimal ediyor (eğer önceki byte 0x10 olsaydı, orta chunk’ın gerçek boyutundan 0x10 daha küçük olduğunu gösterecekti).
- Sonra, ortada freed chunk (b) içinde 2 daha küçük chunk allocate ediliyor (b1 ve b2), fakat
b + b->sizec chunk’ını güncellemiyor çünkü işaret edilen adres olması gerekenden daha küçük. - Ardından, b1 ve c free ediliyor.
c - c->prev_sizehâlâ b’yi (şimdi b1) işaret ettiği için ikisi birleştirilip tek bir chunk oluyor. Ancak b2 hâlâ b1 ile c arasında içerde kalıyor. - Son olarak, bu bellek alanını geri almak için yeni bir malloc yapılınca aslında b2 içerecek şekilde allocate ediliyor ve yeni malloc sahibi b2’nin içeriğini kontrol edebiliyor.
Bu görsel saldırıyı mükemmel şekilde açıklıyor:
.png)
https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
Modern glibc hardening & bypass notes (>=2.32)
- Safe-Linking artık her singly linked bin pointer’ı
fd = ptr ^ (chunk_addr >> 12)şeklinde saklayarak koruyor; bu yüzden sadecesize’ın düşük baytını flipleyen bir off-by-one genellikle Tcache poisoning’in çalışabilmesi için heap leak gerektirir. - Pratik bir leakless hile, bir pointer’ı “double-protect” etmektir: zaten kontrol ettiğiniz bir pointer’ı
PROTECT_PTRile encode edin, sonra aynı gadget’ı kullanarak sahte pointer’ınızı encode edin ki alignment kontrolü yeni adresler ifşa etmeden geçsin. - Safe-linking + single-byte corruptions için iş akışı:
- Overlapping-chunk setup yapmak için victim chunk’ı, zaten kontrol ettiğiniz free edilmiş bir chunk’ı tamamen kaplayana kadar büyütün.
- Leak any heap pointer (stdout, UAF, partially controlled struct) ve anahtarı
heap_base >> 12çıkarın. - Yazmadan önce free-list pointer’ları yeniden encode edin—encode edilmiş değeri user data içinde sahneleyin ve sadece single-byte yazma hakkınız varsa sonra memcpy ile aktarın.
- Forge edilmiş pointer doğru şekilde encode edildikten sonra allocation’ları
__free_hookveyatcache_perthread_structgirdilerine yönlendirmek için Tcache bin attacks ile birleştirin.
Modern exploit’leri debug ederken encode/decode adımını prova etmek için minimal bir yardımcı:
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
Son gerçek dünya hedefi: glibc __vsyslog_internal off-by-one (CVE-2023-6779)
- Ocak 2024’te Qualys, CVE-2023-6779’i ayrıntıladı:
__vsyslog_internal()içinde bir off-by-one hata,syslog()/vsyslog()format string’leriINT_MAX’i aştığında tetikleniyor; bu yüzden sonlandırıcı\0glibc 2.37–2.39 sistemlerinde bir sonraki chunk’ın en az anlamlısizebaytını bozuyor (Qualys advisory). - Onların Fedora 38 exploit pipeline’ı:
- Bir overlong
openlog()ident hazırlayın, böylecevasprintfsaldırganın kontrolündeki verinin yanında bir heap buffer döndürür. syslog()çağırarak komşu chunk’ınsize | prev_inusebaytını ezip, onu free edin ve saldırgan verisiyle örtüşecek şekilde konsolidasyona zorlayın.- Örtüşen görünümü kullanarak
tcache_perthread_structmetadata’sını bozuk hale getirin ve sonraki allocation’u__free_hook’a yönlendirip onusystem/root için bir one_gadget ile overwrite edin.
- Bozucu yazmayı bir harness’ta yeniden üretmek için, devasa bir
argv[0]ile fork edin,openlog(NULL, LOG_PID, LOG_USER)çağırın ve sonrasyslog(LOG_INFO, "%s", payload)çalıştırın; buradapayload = b"A" * 0x7fffffff;pwndbg’inheap bins’i tek baytlık overwrite’i hemen gösterir. - Ubuntu bu hatayı CVE-2023-6779 olarak takip ediyor ve bu güvenilir bir off-by-one primitive yapan aynı INT kırpılmasını belgeliyor.
Diğer Örnekler & Referanslar
- https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
- Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
- Off-by-one,
strlen’in bir sonraki chunk’ınsizealanını göz önüne alması nedeniyle oluşur. - Tcache kullanılıyor, bu yüzden genel bir off-by-one saldırısı Tcache poisoning ile arbitrary write primitive elde etmek için işe yarar.
- Asis CTF 2016 b00ks
- Bir off-by-one’ı heap’ten bir adresi leak etmek için kötüye kullanmak mümkün, çünkü bir string’in sonundaki 0x00 baytı bir sonraki alan tarafından overwrite edilir.
- Arbitrary write, off-by-one yazmasını kötüye kullanarak pointer’ı başka bir yere yönlendirip sahte pointer’lar içeren sahte bir struct oluşturulmasıyla elde edilir. Sonra bu struct’ın pointer’ını takip ederek arbitrary write yapılabilir.
- Libc adresi leak edilir çünkü heap mmap ile genişletilirse, mmap ile ayrılan bellek libc’den sabit bir offset’e sahiptir.
- Son olarak arbitrary write,
__free_hookadresine bir one_gadget yazarak kötüye kullanılır. - plaidctf 2015 plaiddb
getlinefonksiyonunda kullanıcı giriş satırlarını okuyan bir NULL off-by-one açığı vardır. Bu fonksiyon içeriğin “key“ini okumak için kullanılır, içeriğin kendisini değil.- Writeup’ta 5 başlangıç chunk’ı oluşturulur:
- chunk1 (0x200)
- chunk2 (0x50)
- chunk5 (0x68)
- chunk3 (0x1f8)
- chunk4 (0xf0)
- chunk defense (0x400) top chunk ile konsolide olmasını önlemek için
- Sonra chunk 1, 5 ve 3 free edilir, böylece:
-
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
- Sonra chunk3 (0x1f8) kötüye kullanılarak null off-by-one ile prev_size `0x4e0`'a yazılır.
- Dikkat edin, başlangıçta ayrılan chunks 1, 2, 5 ve 3'ün boyutlarının ve bu chunk'lardan 4'ünün header'larının toplamı `0x4e0`'a eşittir: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Sonra, chunk 4 free edilir ve başlangıca kadar tüm chunk'ları kapsayan bir chunk üretilir:
- ```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 ]
- Sonra, orijinal chunk 1'i doldurmak için `0x200` byte ayrılır.
- Ve başka bir `0x200` byte daha ayrılır, chunk2 yok edilir ve bu yüzden hiçbir leak yok ve bu işe yaramıyor mu? Belki bu yapılmamalı.
- Sonra, chunk2'yi overwrite ederek chunk5'e ulaşan 0x58 "a" ile başka bir chunk ayrılır ve chunk5'in fast bin chunk'ının `fd`'si `__malloc_hook`'a işaret edecek şekilde değiştirilir.
- Sonra, 0x68 boyutunda bir chunk ayrılır; böylece `__malloc_hook` içindeki sahte fast bin chunk bir sonraki fast bin chunk olur.
- Son olarak, yeni bir 0x68 fast bin chunk ayrılır ve `__malloc_hook` bir `one_gadget` adresi ile overwrite edilir.
## References
- [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]
> AWS Hacking'i öğrenin ve pratik yapın:<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;">\
> GCP Hacking'i öğrenin ve pratik yapın: <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;">
> Azure Hacking'i öğrenin ve pratik yapın: <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>HackTricks'i Destekleyin</summary>
>
> - [**abonelik planlarını**](https://github.com/sponsors/carlospolop) kontrol edin!
> - **💬 [**Discord grubuna**](https://discord.gg/hRep4RUj7f) veya [**telegram grubuna**](https://t.me/peass) katılın ya da **Twitter'da** bizi **takip edin** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Hacking ipuçlarını paylaşmak için** [**HackTricks**](https://github.com/carlospolop/hacktricks) ve [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github reposuna PR gönderin.
>
> </details>


