Makale Özeti

Hafıza alan taşması ya da İngilizce adıyla ‘Buffer Overrun’. Bu tanımlamayı yakından tanımıyor olsanız bile kesin duymuşsunuzdur. MSDN’de yaptığım son aratmada ‘Buffer Overrun’ ifadesi 202 başlık döndürdü. İşte bunlardan ilk 20’sinden bazı başlıklar:

Makale

Hafıza alan taşması ya da İngilizce adıyla ‘Buffer Overrun’. Bu tanımlamayı yakından tanımıyor olsanız bile kesin duymuşsunuzdur. MSDN’de yaptığım son aratmada ‘Buffer Overrun’ ifadesi 202 başlık döndürdü. İşte bunlardan ilk 20’sinden bazı başlıklar:

MS03-039: Buffer Overrun in RPCSS May Allow Code Execution
MS02-065: Buffer Overrun in Microsoft Data Access Components Can Lead to Code Execution (MDAC 2.6)
MS03-044: Buffer Overrun in Windows Help and Support Center Could Lead to System Compromise
MS03-036: Buffer Overrun in WordPerfect Converter Could Allow Code Execution

Korkutucu değil mi? Temel mesaj açık: Buffer overrun diye bir problem var ve bu problem yüzünden kötü niyetli birileri istedikleri kodları sizin sisteminizde çalıştırabilirler. Sisteminizde kontrol kötü niyetli bir kişinin eline neredeyse sınırsızca geçebilir.

Korkutucu olmakla birlikte, doğru önlemleri aldığınız taktirde hafıza alan taşması başınızı çok sık ağrıtabilecek bir sorun değil.

Nedir hafıza alan taşması?

Destek hafıza alanında (stack) ayrılmış bir alana, o alanın alabileceğinden daha büyük veri kopyalandığı zaman hafıza alan taşması gerçekleşir. Atağı yapan kişi ne yaptığını iyi biliyorsa, normalde içinde bulunulan işlevin dönüş adresinin yerine, bu kopyalanan gereğinden büyük verideki bir kısım yazılır ve programın akışı saldırganın istediği bir bellek adresine yönlenmiş olur. Artık çalışan saldırganın kodudur, ama kullandığı ortam sizin programınızın normalde sahip olduğu ortamdır. Hafıza alan taşmasının olabilmesi için, kopyalanan verilerin büyüklüklerinin tam olarak test edilmiyor olması gerekir. Genel olarak bu problem, C/C++ gibi hafıza yönetiminin doğrudan yapılabildiği dillerde görülür. C# gibi daha üst seviye dillerde hafıza alan taşmasına sebep olabilmeniz çok zordur, ama bu gibi dillerde yazdığınız kodlarda özellikle yönetilmeyen (unmanaged) kodlara çağrıda bulunuyor ve veri gönderiyorsanız yine tehlike altındasınız demektir. Sadece hafıza alan taşması için değil SQL aşılaması gibi başka tür saldırılara karşı da her zaman kullanıcıdan aldığınız verinin gereken biçim ve uzunlukta olduğunu kontrol etmeniz gerekir.

Hafıza alan taşması 4 çeşittir: Destek alan (stack) tabanlı taşmalar, yığın hafıza (heap) taşmaları, v-table ve işlev işaretçisi üzerine yazan taşmalar, istisna işleyici (exception handler) üzerine yazan taşmalar.

Nasıl zarar verir?

Hafıza alan taşması erişim ihlali hatası ya da ilgili işlemin sona ermesi olarak sonuçlanabilir. Bazı durumlarda program çalışmaya devam eder ama değişkenlerin değerleri taşmaya bağlı olarak programın akışıyla ilgisi olmayan bir şekilde değiştiğinden yanlış verilerle dengesiz bir çalışma devam eder. Bunun sonucunda etkisinin ne olacağını önceden bilemeyeceğiniz belirsiz sonuçlar ortaya çıkabilir.

Normal çalışma sırasında bir yordam (procedure) çağrıldığında, destek hafıza alanında (stack) çağıran kodun yerini gösteren bir geri dönüş adresi yazılır. Yordam normal çalışmasını bitirdiğinde programın akışı bu işaretlenen adres yardımıyla kaldığı yere döner. Parametreler ve yerel değişkenler hafıza destek alanında geri dönüş adresinin sonrasına konulur. Yordamın sonunda hafıza destek alanı geriye doğru çözülür ve alan boşalmış olur. Destek alanı geri dönüş adresine kadar geriye doğru çözüldüğünde programın akışı buradan yordamın çağrıldığı noktaya atlayarak devam eder.

Hafıza alan taşması gerçekleştiğinde ilgili alana yazılacak veri konusunda bir sınır yoktur. Saldırganlar hafıza destek alanındaki hemen her şeyin üzerine yazabilirler. Yetenekli bir saldırgan geri dönüş adresinin üzerine de yazabilir, üstelik kodun yönlenmesini istediği noktaya yönlendirecek veriyle. Böylece, programınızın sahip olduğu haklarla kötü niyetli bir kişinin istediği kodlar sisteminizde çalışmaya başlamış olur. Eğer bu haklar yönetici hakları ya da yüksek nitelikli haklarsa çok büyük zararlar ortaya çıkabilir.

Bu yüzden yukarıda belirttiğimiz gibi verilerin biçim ve büyüklüklerini kontrol etmeniz yanı sıra, uygulamalarınızı gerekli en az ayrıcalık kümesiyle çalıştırıyor olmanız da iyi bir risk mücadele stratejisidir.

Bir hafıza alanı taşması örneği:

Hafıza taşmasının sık rastlanan türde bir örneğine bakalım:

void Sakincali (const char* denetlenmemisVeri)
{
char yerelDegisken[4];
int baskabirYerelDegisken;
strcopy(yerelDegisken, denetlenmemisVeri);
}

Bu kodda 4 byte veri alabilecek bir alan tanımlanmışken gerekli kontrolün yapılması ihmal edilmiştir. Eğer denetlenmemişVeri 4 byte’tan büyük girilirse strcopy işlevi destek hafıza alanındaki dönüş adresinin üzerine yazabilir. Bunu yeterince bilgili bir saldırgan yaptığında dönüş adresinin olduğu yere taşma sonucu ne yazılacağını hesaplayarak kendi amaçlarıyla kullanacağı bir prosedüre yönlendirme yapabilir. Böylece programınızın iyi niyetle kullandığı hakları kötü niyetlerle kullanmak üzere devralmış birtakım kodlar sisteminizde çalışmaya başlar.

Microsoft Visual C++.Net tehlikeye açık kodları bazı tür hafıza taşması saldırılarından larından korumak için

Strcopy türü güvensiz işlevlerin kullanmasıyla oluşan türde hafıza taşma saldırılarını sınırlamak için /GS derleyici opsiyonuna sahiptir. Bu opsiyon standart yerel (native) kod yazarken kullanılmalıdır. Yönetilen koda (managed code) ya da .NET IL’e yönelik değildir.

Aslında .NET ortamında VB.NET ya da C# kullanıyorsanız, hafıza taşması uykularınızı kaçıracak bir problem değildir, ama özellikle yönetilmeyen kodlara yaptığınız çağrılarda verilerinizi kontrol etmeden parametre olarak gönderiyorsanız, risk sizin için de geçerlidir.

Genel bir ilke olarak dışarıdan aldığınız verilerin biçim ve uzunluk olarak doğru ve zararsız olduğunu her zaman kontrol etmeniz gerekir. Suçsuzluğu ispat edilene kadar kullanıcı girdilerini suçlu kabul ederseniz, başınız ağrımaz.