# Heap Overflow {{#include ../../banners/hacktricks-training.md}} ## Temel Bilgiler Heap overflow, [**stack overflow**](../stack-overflow/index.html) gibi ama heap'te gerçekleşir. Temelde, bazı verileri depolamak için heap'te ayrılmış bir alanın olduğu ve **depolanan verinin ayrılan alandan daha büyük olduğu** anlamına gelir. Stack overflow'larda, talimat işaretçisi veya stack çerçevesi gibi bazı kayıtların stack'ten geri yükleneceğini biliyoruz ve bunu kötüye kullanmak mümkün olabilir. Heap overflow'larda ise, **varsayılan olarak heap parçasında depolanan herhangi bir hassas bilgi yoktur**. Ancak, hassas bilgiler veya işaretçiler olabilir, bu nedenle bu güvenlik açığının **kritikliği** **hangi verilerin üzerine yazılabileceğine** ve bir saldırganın bunu nasıl kötüye kullanabileceğine **bağlıdır**. > [!TIP] > Overflow offset'lerini bulmak için [**stack overflow'larda**](../stack-overflow/index.html#finding-stack-overflows-offsets) olduğu gibi aynı desenleri kullanabilirsiniz. ### Stack Overflow'lar vs Heap Overflow'lar Stack overflow'larda, güvenlik açığının tetiklenebileceği anda stack'te bulunacak düzen ve veri oldukça güvenilirdir. Bunun nedeni, stack'in lineer olması, her zaman çarpışan bellek içinde artması, **programın çalışmasının belirli yerlerinde stack belleğinin genellikle benzer türde verileri depolamasıdır** ve her fonksiyon tarafından kullanılan stack parçasının sonunda bazı işaretçilerle belirli bir yapıya sahip olmasıdır. Ancak, heap overflow durumunda, kullanılan bellek lineer değildir, **ayrılan parçalar genellikle bellek içinde ayrı konumlarda** (birbirinin yanında değil) bulunur çünkü **boyutlarına göre ayrılan alanları** ayıran **bins ve zonlar** vardır ve **önceki serbest bellek kullanılır** yeni parçalar ayırmadan önce. **Hedef nesnenin, heap overflow'a karşı savunmasız olan nesneyle çarpışacağını bilmek karmaşıktır.** Bu nedenle, bir heap overflow bulunduğunda, **istenen nesnenin, overflow edilebilecek nesneden sonra bellekte gelmesini sağlamak için güvenilir bir yol bulmak** gereklidir. Bunun için kullanılan tekniklerden biri **Heap Grooming**'dir, örneğin [**bu yazıda**](https://azeria-labs.com/grooming-the-ios-kernel-heap/) açıklanmaktadır. Yazıda, iOS çekirdeğinde bir alanın bellek parçalarını depolamak için bellek kalmadığında, bir çekirdek sayfası ile genişletildiği ve bu sayfanın beklenen boyutlardaki parçalara bölündüğü açıklanmaktadır (iOS sürüm 9.2'ye kadar, ardından bu parçalar bu saldırıların istismarını zorlaştırmak için rastgele bir şekilde kullanılır). Bu nedenle, önceki yazıda bir heap overflow gerçekleştiğinde, overflow edilen nesneyi bir kurban nesnesiyle çarpışmaya zorlamak için, **tüm serbest parçaların doldurulmasını sağlamak ve yeni bir sayfanın oluşturulmasını sağlamak için birkaç `kalloc` birkaç iş parçacığı tarafından zorlanır.** Belirli bir boyuttaki nesnelerle bu doldurmayı zorlamak için, **iOS mach portu ile ilişkili dışarıda ayrılan bellek** ideal bir adaydır. Mesajın boyutunu şekillendirerek, `kalloc` ayrımının boyutunu tam olarak belirlemek mümkündür ve ilgili mach portu yok edildiğinde, ilgili ayrım hemen `kfree`'ye geri verilecektir. Sonra, bu yer tutuculardan bazıları **serbest bırakılabilir**. **`kalloc.4096` serbest listesi, son giren ilk çıkar sırasına göre elemanları serbest bırakır**, bu temelde, bazı yer tutucular serbest bırakıldığında ve istismar, overflow'a karşı savunmasız nesneyi ayırmaya çalışırken birkaç kurban nesnesi ayırmaya çalışırsa, bu nesnenin bir kurban nesnesinden sonra gelmesi olasıdır. ### Örnek libc [**Bu sayfada**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) bir temel Heap overflow emülasyonu bulmak mümkündür; bu emülasyon, bir sonraki parçanın prev in use bitini ve prev boyutunun konumunu üzerine yazarak **kullanılan bir parçayı konsolide etmenin** (kullanılmamış gibi düşünmesini sağlayarak) ve **sonra tekrar ayırmanın** mümkün olduğunu göstermektedir. [**Protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) adlı başka bir örnek, bir **heap overflow**'un istismar edilebileceği çok temel bir CTF örneğini göstermektedir; bu örnekte **bayrağı almak için** kazanan fonksiyonu çağırmak mümkündür. [**Protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) örneğinde, bir buffer overflow istismar ederek, **yakın bir parçaya bir adresi üzerine yazmanın** mümkün olduğu gösterilmektedir; bu adrese **kullanıcıdan rastgele veriler** yazılacaktır. ### Örnek ARM64 [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) sayfasında, yürütülecek bir komutun overflow edilen parçanın sonraki parçasında depolandığı bir heap overflow örneği bulabilirsiniz. Bu nedenle, yürütülen komutu, kolay bir istismar ile üzerine yazarak değiştirmek mümkündür: ```bash python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt ``` ### Diğer örnekler - [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/) - Bir Heap Overflow elde etmek için Integer Overflow zafiyetini kullanıyoruz. - Bir `struct` içindeki bir işlevin işaretçilerini bozarız, taşan parçanın içine `system` gibi bir işlev ayarlayıp kod yürütme elde ederiz. ### Gerçek Dünya Örneği: CVE-2025-40597 – `__sprintf_chk`'nin Yanlış Kullanımı SonicWall SMA100 firmware 10.2.1.15'te ters proxy modülü `mod_httprp.so`, **0x80-byte** boyutunda bir heap parçası ayırır ve ardından içine birkaç dizeyi `__sprintf_chk` ile birleştirir: ```c char *buf = calloc(0x80, 1); /* … */ __sprintf_chk(buf, /* destination (0x80-byte chunk) */ -1, /* <-- size argument !!! */ 0, /* flags */ "%s%s%s%s", /* format */ "/", "https://", path, host); ``` `__sprintf_chk`, **_FORTIFY_SOURCE**'un bir parçasıdır. **Pozitif** bir `size` parametresi aldığında, sonuçta oluşan string'in hedef tamponun içine sığdığını doğrular. **`-1` (0xFFFFFFFFFFFFFFFF)** geçirerek, geliştiriciler etkili bir şekilde **sınır kontrolünü devre dışı bıraktılar**, güçlendirilmiş çağrıyı klasik, güvensiz `sprintf`'ye geri döndürdüler. Aşırı uzun bir **`Host:`** başlığı sağlamak, bu nedenle bir saldırganın **0x80 baytlık parçayı taşmasına ve sonraki heap parçasının meta verilerini bozmasına** olanak tanır (tcache / fast-bin / small-bin, ayırıcıya bağlı olarak). Bir çökme şu şekilde yeniden üretilebilir: ```python import requests, warnings warnings.filterwarnings('ignore') requests.get( 'https://TARGET/__api__/', headers={'Host': 'A'*750}, verify=False ) ``` Pratik istismar, kontrol edilebilir bir nesneyi savunmasız parçanın hemen arkasına yerleştirmek için **heap grooming** gerektirecektir, ancak kök neden iki önemli çıkarımı vurgular: 1. **_FORTIFY_SOURCE gümüş bir mermi değildir** – yanlış kullanım korumayı geçersiz kılabilir. 2. Her zaman **doğru tampon boyutunu** `_chk` ailesine iletin (veya daha iyisi, `snprintf` kullanın). ## References * [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/) {{#include ../../banners/hacktricks-training.md}}