İçindekiler
Bir programın belleğinde taşma hatası bulmak, saldırgan için eskiden kilidi açık bir kapı keşfetmeye benzeyebilirdi. Ancak modern işletim sistemleri artık bu kapının arkasına hareketli koridorlar ve yalnızca okunabilen odalar yerleştiriyor. ASLR adresleri tahmin edilemez hâle getirirken DEP veriyi kod olarak çalıştırmayı engelliyor. Bu mekanizmalar yazılım hatalarını ortadan kaldırmaz; hataların güvenilir biçimde istismar edilmesini zorlaştırır.
``
Önce bellek düzenini anlayalım
Çalışan bir süreç; program kodu, yığın, dinamik bellek ve paylaşılan kütüphaneler gibi farklı bölgelerden oluşur. Klasik bir bellek taşması saldırısında amaç, kontrol verisini değiştirerek işlemciyi saldırganın seçtiği adrese yönlendirmektir. Sabit adresler ve çalıştırılabilir veri alanları varsa bu iş görece kolaylaşır.
Modern savunmanın temel fikri iki soruya dayanır:
- Saldırgan hedef kodun nerede olduğunu bilebilir mi?
- Saldırganın yerleştirdiği veri işlemci tarafından kod olarak çalıştırılabilir mi?
ASLR ilk soruya, DEP ise ikinci soruya karşı direnç üretir.
ASLR: Bellek haritasını karıştırmak
Address Space Layout Randomization, program her çalıştığında önemli bellek bölgelerini farklı sanal adreslere yerleştirir. Yürütülebilir dosya, kütüphaneler, stack ve heap böylece aynı konumda görünmez.
Adres seçimi için $n$ bitlik etkili rastgelelik varsa teorik olasılık uzayı:
\[N = 2^n\]Tek tahminde doğru adresi bulma olasılığı yaklaşık $1/2^n$ olur. Örneğin 20 bit entropi, teorik olarak $2^{20}=1.048.576$ farklı olasılık demektir. Gerçek güvenlik; mimariye, hizalama gereksinimlerine ve hangi bölgelerin rastgeleleştirildiğine bağlıdır.
Linux üzerinde bir sürecin bellek bölgeleri savunma amaçlı şöyle incelenebilir:
cat /proc/$$/maps
Bu komut mevcut kabuk sürecinin bellek haritasını gösterir. Komutu farklı süreçlerde çalıştırdığınızda kütüphane ve yığın adreslerinin değişmesi ASLR’nin etkisini gözlemlemeyi sağlar.
DEP: Veri, veri olarak kalsın
Data Execution Prevention, bellek sayfalarının yazılabilirlik ve çalıştırılabilirlik izinlerini ayırır. Linux dünyasında bu yaklaşım sıklıkla NX, yani “No-eXecute” biti adıyla anılır. Stack veya heap üzerindeki bir bölgeye veri yazılabilse bile işlemci bu bölgedeki baytları komut olarak yürütmeyi reddeder.
#include <stdio.h>
int main(void) {
char message[] = "Bu dizi veri bölgesindedir.";
printf("%s\n", message);
return 0;
}
Buradaki message okunup yazılabilen bir veridir; fakat modern korumalar etkinse bulunduğu sayfanın doğrudan makine kodu gibi çalıştırılması beklenmez. DEP, işlemcinin sayfa izinlerini denetleyen donanımsal desteğiyle uygulanır.
| Özellik | ASLR | DEP / NX |
|---|---|---|
| Temel amacı | Adresleri belirsizleştirmek | Veri sayfalarında kod yürütmeyi engellemek |
| Koruduğu alan | Bellek yerleşimi | Sayfa çalıştırma izinleri |
| Tek başına yeterli mi? | Hayır | Hayır |
| Tipik zayıflığı | Adres sızıntıları | Mevcut kodun yeniden kullanılması |
Neden birlikte daha güçlüler?
DEP, yeni yerleştirilmiş zararlı kodun çalıştırılmasını zorlaştırınca saldırgan mevcut program veya kütüphane kodunu kullanmaya yönelebilir. ASLR ise bu mevcut kod parçalarının adreslerini gizler. Başka bir ifadeyle DEP “burada çalıştıramazsın”, ASLR ise “aradığın şeyin nerede olduğunu bilmiyorsun” der.
Yine de bunlar sihirli kalkanlar değildir. Bellek adresi sızdıran bir hata ASLR etkisini azaltabilir; yanlış sayfa izinleri DEP’yi zayıflatabilir. Ayrıca 32 bit sistemlerin dar adres alanı daha düşük entropi sunar. Bu nedenle modern platformlar ASLR ve DEP’yi stack canary, PIE, kontrol akışı bütünlüğü, sandbox ve güvenli programlama teknikleriyle tamamlar.
Sonuç olarak gerçek çözüm, güvenlik açığını kaynağında gidermektir. ASLR ile DEP ise hata yamalanana kadar saldırının maliyetini yükselten, güvenilir exploit geliştirmeyi belirsiz ve kırılgan hâle getiren güçlü savunma katmanlarıdır.
Yorumlar