Makale Özeti

Uygulama geliştiricilerin saldırılara karşı kullanabilecekleri çeşitli teknikler vardır. Bunlardan bir kısmı genel nitelikli tedbirlerdir ve her hangi bir platformda kullanılabilirler, kimisi ise özel durumlarda geçerlidir.

Makale

Uygulama geliştiricilerin saldırılara karşı kullanabilecekleri çeşitli teknikler vardır. Bunlardan bir kısmı genel nitelikli tedbirlerdir ve her hangi bir platformda kullanılabilirler, kimisi ise özel durumlarda geçerlidir. Tüm bu teknikler içinde en genel olarak kullanılması gerekenleri sıralayacak olursak:
- Kodunuz, gerekli en az hakla çalışsın
- Varsayılan ayarlarınız güvenli olsun.
- Kullanıcı girdilerini doğrulayın
- Güvenlik stratejinizi belirsizlik ya da karmaşıklığa dayandırmayın.
- Gizli bilgileri depolamayın.
- DPAPI (Data Protection Application Programming Interface) kullanın.
- Programınızın başarısızlık durumlarında ‘akıllıca düşmesini’ sağlayın.
- Güvenliği test edin.
- Hatalarınızdan öğrenin.
Şimdi bunlardan yaygın birkaç tanesini daha detaylı inceleyelim.

Mümkün olan en düşük haklarla çalışın

Uygulamanızda oluşabilecek bir açıktan dolayı kontrol saldıran kodun ya da kişinin eline geçerse, uygulamanızın normalde sahip olduğu haklar da saldırgana geçmiş olur. Üstelik uygulamanız saldırı altında değilse bile, gerekli en az haklarla çalışmak önemli bir prensiptir. Kullanıcılar, bazen hatalı kullanımlarıyla saldırganlar kadar zarar verebilirler. Uygulamanızı çok güvenli yazdığınızı düşünüyor olsanız bile, yararlandığınız bazı alt seviye sistemler ya da metotlarda sonradan ortaya çıkabilecek açıklar da sizin uygulamanızın bir müddet sonra saldırıya açık hale gelmesine sebep olabilirler.
Diyelim ki kodunuzda bellek taşmasına dayalı bir zayıflık var ve bir saldırgan bu durumdan yararlandı. Sonuç olarak, saldırgan, kodunuzun sahip olduğu haklara aynen sahip olarak işi ele almış olacaktır. Bu durumda, uygulamanızı yazarken mümkün olan en düşük hakları kullanıp kullanmadığınız çok büyük önem kazanır. Yönetsel haklara gerek olmadığı halde yönetsel haklar isteyen bir uygulama yazdıysanız, gereksiz risk aldınız demektir.
Gereksiz yere üstün hakları kullanmanın bir diğer sakıncası da virüslerdir. Virüsler, bulaştıkları sistemde aktif kullanıcı haklarıyla davrandıkları için, bu haklar yeterince genişse sistem dosyalarının üzerine yazmaya kadar büyük zararlar verebilmektedirler.
Kullanıcılarının yönetsel haklara sahip olmasını gerektiren programlar yazmak kolaydır, çünkü izin hatalarıyla uğraşmanız gerekmez. Ama bunu yapmayın, bedeli çok ağır olabilir.

Varsayılan ayarlarınız güvenli olsun

Söylerken basit gelse de güvenli varsayılan ayarları sağlamak bir programcı için çok da kolay değildir. Güvenli varsayılan ayarları sağlamak için dikkat edebileceğimiz önemli bir nokta, arayüzlerimizi mümkün olduğu kadar basit yazmaktır. Bunu sağlamak için uygulamanızın ‘public’ metotlarının olabildiğince az olması gerekir. Bir arayüz için public metotları ancak ve ancak gerçekten gerekliyse kullanmalısınız.
Yararlı olabilecek bir başka yaklaşım da uygulamanızın en sıklıkla kullanılan özelliklerini tespit edip bunların güvenliği üzerinde çok daha hassas durmanızdır. Yine güvenlik açısından daha az kullanılan diğer özellikleri varsayılan olarak kapalı durumda tutmalısınız.
Tüm bunların ortak hedefi ‘tehlike alanını’ küçültmektir, bir başka deyişle hedef küçültmek. Bir çatışma anında daha az zarar görmek için hedef küçültmekten çok da farklı bir mantık içermez.
Az kullanılan özellikleri güvenli hale getirmek daha zordur, bütçeniz ve zamanınız açısından her zaman tüm özellikleri en güvenli hale getiremeyebilirsiniz. Bu durumda seçici davranmalı ve sık kullanılan özelliklerden başlayarak güvenliği sağlamalısınız. Az kullanılan özellikleri ise varsayılan olarak kapalı duruma getirmek önemli bir adımdır. Böylelikle bu tür bir özelliğe bağlı bir saldırı durumunda çok daha az kullanıcınız tehdit altında olacaktır.
Belki kullanıcılarınızın işlerine yarayacak bir özelliği açmak zorunda kalmaları olumsuz bir durum gibi gözükebilir, biraz öyledir de. Ama inanın, kullanıcı için o özellik gerçekten gerekliyse, onu bulması, ayarlarını öğrenmesi vb çok da zor olmayacaktır.
Kullanılmayan tüm platform servislerini kapatarak ve uygulamanız tarafından sunulan arayüzlerin sayısını kısıtlayarak olası atak cephelerini de azaltmış oluyorsunuz.
Bu konuda en belirgin uygulama Windows Server 2003’te görülebilir. Windows Server 2003’ün 2000’e göre en önemli farklılıklarından biri çok daha sıkı güvenlik içermesidir. Bunu sağlayan temel faktörlerden biri de hizmetlerin çoğunluğunun kapalı gelmesidir.

Kullanıcı girdilerini doğrulayın

Klişe bir lafın tersi ama yine klişe: “Masumluğu ispatlanana kadar tüm girdiler suçludur.” Girdi nereden geliyor olursa olsun, eğer kaynağı güven sınırlarınızın dışındaysa, girdiyi doğrulayın! Bu kaynak ister bir paylaşılan dosya, ister bir veritabanı, ister bir kullanıcı olsun. Uygulamalara yönelik tehditlerin çoğu kullanıcı girdileri üzerindendir. Bir yazılımcı olarak, doğrulanmış girdilere bakmalı, kalan tüm girdileri reddetmelisiniz. Geçersiz veriyi seçip reddetmeye kalanı kabul etmeye kalkarsanız, hata yapabilirsiniz. Ancak gerçekten doğrulayabildiğiniz verileri kabul edin ve kalanı reddedin.
Doğrulamayı asla sadece istemci tarafında yapmayın. Hatanın erken fark edilip performans kayıplarının engellenmesi açısından yapılabilen doğrulamaların istemci tarafında gerçekleştirilmesi doğru bir yaklaşımdır, ama bu yeterli değildir. Aynı doğrulamalar sunucu tarafında da yapılmalıdır. Aksi takdirde istemci tarafı çalışan kodcuklar kötü niyetli bir kişi tarafından aşılabilir.
Sunucu tarafında mesela veritabanına göndermeden önce veriyi doğrulayabilirsiniz. Beklenenden geniş olan ya da tehlikeli karakter ya da kelimeler içeren girdileri de reddedebilirsiniz. Bu tür tehlikelere örnek olarak kodcuk unsurları (<script>, <object> gibi) özel SQL karakterleri ve anahtar kelimeleri (--, INSERT, xp_cmdshell gibi) ya da dosya sisteminde gezinme sağlayabilecek karakterler (…\) verilebilir.
Girdilerin ‘masumiyeti’nden emin olmak için kullanılabilecek çok güçlü yöntemler vardır. ‘Regular Expression’ları kullanmak bunların belki en güçlüsüdür. Mesela şu ifadeyi düşünün:
(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* )
Bu ifade girilen bir adresin Internet e-posta adresine uygun olduğunu kontrol eder.

Derinlikli savunma

Şaşar beşer! İnsan, hata yapar. Bu da tek bir savunma hattının yeterli olmadığı anlamına gelir. Güvenlik kademelerinin sayısını artırarak uygulamanızın güvenliğini artırabilirsiniz.
Arka planda SQL Server’da duyarlı veriler tutan bir Web uygulamanız olduğunu düşünün. Web sunucusunun önüne bir firewall koymak bir güvenlik önlemidir. SSL kullanmak güvenlik seviyesini artırır. Ama bunların yanı sıra SQL Server’ın önüne ikinci bir firewall koymak ve iç ağdaki bilgisayarların IPSec kullanmasını zorunlu tutmak da fena fikir değildir. Önceki tedbirleri almış olmak, bunları gereksiz kılmaz.
Bu, aslında eski kalelerdeki iç içe surlar kullanımından pek farklı bir yaklaşım değildir. Bu sayede, bir noktada gedik verseniz bile, tüm sistemi kaybetmeden savunmaya devam etme şansınız olur.
Bir .exe uygulamanız ve bunun içinden kullandığınız .dll’ler olduğunu düşünün. Tanıtlama ve yetkilendirmeyi sadece exe’de yapmanızın yeterli olduğunu düşünebilirsiniz. Ama ya kötü niyetli bir kullanıcı exe’yi kullanmadan dll’lere ulaşmanın bir yolunu bulursa? Bu durumda exe’nin yanı sıra dll’lerde de tanıtlama ve yetkilendirme yapmak akılcı bir yaklaşım olarak ortaya çıkıyor.
Son bir savunma hattı olarak, dosya ve klasörlerin ACL’lerini kullanmayı unutmayın.
Ne derinlikte bir savunma kuracağınıza karar vermek için önceden tehdit modellemesi yapmanız faydalı olacaktır. Unutmayın ki, güvenliği artırmanız performansla ödemeniz anlamına gelebilir. Aradaki dengeyi kendi durumunuzu doğru analiz ederseniz doğru olarak kurabilirsiniz.