Buffy the Overflow Slayer
Buffer overflow, Türkçe meali ile arabellek taşması zafiyeti ilk olarak 1960’lı yıllarda sistemlere sızmak için istismar edilmeye başlandı. 1988 yılında internet üzerinden yayılan ve ilk solucan olması ile ünlü olan Morris solucanı da arabellek taşması zafiyetini istismar ederek sistemlere sızıyor ve yayılıyordu. Arabellek taşması zafiyetinin keşfi ve istismar edilme macerası kimileri için uzun seneler önce başladı ve aradan 50 yıl geçmiş olmasına rağmen bu zafiyet halen keşfedilmeye ve istismar edilmeye devam edilmektedir.
Arabellek taşması zafiyetini tam olarak anlayabilmek, kendi istismar aracınızı (exploit) hazırlayabilmek, bu konu ile ilgili yazılmış olan makalelerde kaybolmamak ve Metasploit aracına bağımlı kalmamak için C programlama dili, Assembly programlama dili ve x86 mimarileri konularında bilgi sahibi olmanız gerekmektedir.
1996 yılında Phrack‘ın 49. sayısında yer alan Smashing The Stack For Fun And Profit makalesi, arabellek taşması zafiyetlerinin istismar edilmesine büyük oranda ivme kazandırdı. Benim için ise bu macera 2004 yılında, The ShellCoder’s Handbook kitabını Amazon’dan sipariş etmem ile başlamıştı fakat assembly konusunda hiçbir bilgim olmadığı için sadece okumakla yetinmiş, kafamda bir çok soru işareti oluşmuştu. Ancak aradan zaman geçtikçe ve assembly ile haşır neşir oldukça taşlar daha hızlı yerine oturdu.
Arabellek taşması kısaca ve kabaca hatalı bir şekilde kullanılan fonksiyonlardan (strcpy, sprintf vs.) oluşan bir programda yer alan dinamik değişkenlere (variable), saklama kapasitelerinden daha fazla miktarda veri yüklenmesi ile oluşan duruma denir. Kapasite aşımı sayesinde programın akışı değiştirilerek normal akışta yer almayan kodlar (komutlar) çalıştırılabilir. (exploiting)
Yazım yığın tabanlı bellek taşmasını (stack-based overflow) konu aldığı için öncelikle yığın (stack) nedir kısaca ondan bahsedeyim.
Yığın, programların dinamik değişkenlerinin (variable) geçici süreliğine hafızada tutulduğu bölgeye verilen isimdir. Bu bölgede tanımlanmış dinamik değişkenler tutulduğu gibi bir fonksiyon çağrılmadan önce akışın fonksiyon çağrıldıktan sonra kaldığı yerden devam edebilmesi için gereken adreste (geri dönüş adresi) tutulabilir, saklanabilir.
Bir fonksiyon çağrılmadan önce bu fonksiyonda kullanılacak olan parametreler ile saklanmış, depolanmış (stored) EIP ve EBP kaydedicileri (register) yığına (stack) kopyalanır. Fonksiyondaki işlemler tamamlandıktan sonra saklanmış, depolanmış (stored) EIP kaydedicisi (register) yığından (stack) alınarak EIP kaydedicisine kopyalanır ve programın akışı kaldığı yerden devam eder.
Örnek olarak A ve B fonksiyonundan oluşan bir program düşünelim ve A fonksiyonu içinden B fonksiyonunun çağrıldığını ve 128 byte büyüklüğündeki bir belleğe (array) 136 byte uzunluğunda ve ‘A’ (0x41 hex değeri) karakterinden oluşan bir dizini (string) kopyaladığımızı varsayalım.
#include <string.h> void B(char *buf) { char ms[128]; strcpy(ms, buffer); } int A (int argc, char **argv) { B(argv[1]); }
Bu kopyalama neticesinde saklanmış EIP kaydedicisi (register) üzerine veri yazabildiğimiz için ve bu veri (adres), çağrılan fonksiyon tamamlandıktan sonra EIP kaydedicisine kopyalanacağı için bu adresi değiştirerek programın akışını değiştirebilmekteyiz.
Belleğe 136 bayttan daha fazla veri yazılacak olursa bu veriler yığına kopyalanmaya devam edecektir. Bu durumda programa girdi olarak çalıştırılmasını istediğimiz kodu belirtebilir ve akışı (stored EIP) bu koda yönlendirerek (JMP ESP komutu)a arabellek taşması zafiyetini istismar edebiliriz.
Yığın tabanlı arabellek taşması zafiyeti ve istismar edilmesi kısaca ve kabaca bundan ibaret fakat bunu bir örnekle süslemeden yazıyı tamamlamak amaca hizmet etmeyeceği için hemen örneğimize geçelim.
Örnek olarak istismar edeceğimiz programın adı ASX to MP3 Converter. CVE-2009-1642 numaralı CVE ID’sine göre bu programın 3.0.0.7 sürümünde asx uzantılı dosyalarda kullanılan HREF nitelemesinde (attribute) yığın tabanlı arabellek taşması zafiyeti olduğu belirtiliyor.
Bu açıklama üzerine asx uzantılı bir dosya yaratan ve içine “http://AAAAAAAAAAAA (30000 tane)” dizisi kopyalayan ufak bir program hazırlıyoruz ve daha sonrasında programı çalıştırdığımızda EIP kaydedicisine müdahale ederek zafiyetin varlığını teyit edebiliyoruz.
Fakat kaçıncı bayttan itibaren EIP kaydedicisine yazdığımızı deneme yanılma yolu ile tespit etmek zaman alacağı için hemen bu iş için tasarlanmış olan ve Metasploit aracı içinde yer alan pattern_create uygulamasına başvuruyoruz ve 30000 bayt büyüklüğünde bir dizi oluşturarak bu diziyi programımıza kopyalayarak çalıştırıyoruz. Bu defa EIP kaydedicisinde yer alan değeri pattern_offset uygulamasına girdi olarak verdiğimizde uygulama bize kaçıncı bayttan itibaren EIP kaydecisi üzerine veri yazmaya başladığımızı belirtiyor.
Programımızı aşağıdaki şekilde güncelledikten sonra çalıştırdığımızda EIP kaydedicisini tekrar kontrol ediyoruz.
Fakat görünen o ki EIP kaydedicisine fazladan 1 bayt A gelmiş ve EIP kaydedicisi 42424242 (BBBB) yerine 42424241 (BBBA) değerine sahip olmuş. Programımızda son bir değişiklik yaptıktan sonra asx uzantılı dosyayı tekrar oluşturup programa yüklediğimizde bu defa başarıyla EIP kaydedicisi üzerine istediğimiz değeri yazabildiğimizi görebiliyoruz.
Arabellek taşması ile yığına yeterli miktarda veri yazıp yazamadığımızı kontrol etmek için (shellcode yığında yer alacağı için 400 bayt yeterli olacaktır) programımıza aşağıdaki gibi bir stack değişkeni ekliyor, tekrar çalıştırıyor ve yığına yazabildiğimizi görüyoruz.
Amacımız hazırladığımız kodu (shellcode) yığına yazmak ve depolanmış, saklanmış EIP kaydedicisini yığına yönlendirmek (JMP ESP) olduğu için öncelikle Metasploit’in son sürümünün yüklü olduğu bilgisayarımızda (şuan için 3.5.0) hesap makinası uygulamasını çalıştıran kodu (shellcode) oluşturuyoruz. Ardından yığına yönlendirmek için kullanacağımız assembly komutunu yine diğer bir Metasploit uygulaması olan msfpescan ile örnek olarak kernel32.dll dosyası üzerinde aratıyoruz. Son olarak istismar aracımızı elde ettiğimiz bu bilgiler ile güncelledikten ve çalıştırdıktan sonra oluşturduğumuz asx dosyasını ASX to MP3 Convertor uygulamasına yüklettiğimizde hesap makinası çalışıyor ve mutlu sona ulaşmış oluyoruz.
Yıllar içinde fazla sayıda bellek taşması zafiyetinin ortaya çıkmış olması ve bu zafiyetleri istismar eden solucanların sistemlere vermiş olduğu zararın milyon doları bulması nedeniyle işletim sistemi üreticileri yayınlamış oldukları her yeni işletim sisteminde ve geliştirme platformlarında bu zafiyetlerin istismar edilmesini önleyici bir dizi tedbir almıştır. DEP, Exec Shield, PaX, ASLR, GS (Buffer Security Check), StackGuard, GCC Stack-Smashing Protector (ProPolice) bunlardan sadece bir kaçıdır. Fakat bu tedbirlerin bir çoğu bir şekilde atlatılabildiği için istismarı zorlaştırmaktan öteye gidememişlerdir.
Bir sonraki yazıda görüşmek dileğiyle herkese güvenli günler dilerim…