12 Mart 2009Script Kodlarken Güvenlik Önlemleri…
Aslında kısa bir şekilde bir konuya değineceğim. Bazı şahıslar scriptler yapıp satarak bir şekilde ekmek parası derdindeler lakin ekmek parası kazanacağım derken de yapılan bir sistemin baştan savma olmaması gerek. Geçenlerde ufak bir script adını vermeyeceğim elime geçti ve biraz inceleme fırsatım oldu. Scriptteki ilk gözüme çarpan şey kullanıcılardan alınan verilerin iyi süzülüp vt ye kaydedilmemesiydi. Hadi bunu geçtik diyelim bir php betiğinin admin klasöründe olmasının nasıl bir güvence altında olduğunu anlamak inan o kadar zor ki.
Yani insan bunu acaba admin dizinine atarak o dosyayı koruduğunu mu sandı yoksa eski versiyonlardan kalan işe yaramayan bir php betiğimiydi orda yıllanmaya yüz tutan
Bu betik hiç bir şekile güvenlik altına alınmamış ve dışarıdan veri post edilerek veritabanına ekleme yapılabilmekteydi. Yazının başında da değindiğim verilerin iyi süzülmemesi de bu açığı biraz daha ateşli tetikleyerek admin kısmında javascript kod çalıştırılmasına izin vermekteydi neyseki script yapımcısına bildirdim ve açığı kapadığını bildirdi ama bu açıktan haberdar olup da patch yapan kaç kişi vardır bilinmez.
Böyle olunca da istenirse admin cookie bilgileri alınabilirdi veya yönlendirme kodu eklenerek site başka bir siteye yönlendirebilirdi. Asıl demek istediğim şeye gelince şunları unutmamakda fayda var.
Script Kodlarken;
- Kullanıcıdan alınan verilerin iyi filtrelenmesi gerekiyor. Bunu ilk başta vt ye kaydederken yaparsanız veri listeleme kısmında ekstra işler yapmaktan kurtularak scriptinizin performansınıda bir nebze sağlamış olursunuz.
- Scriptinizin yönetim kısmında bulunan sayfalara mutlak suretle güvenlik fonksiyonları uygulayın. ( Define ile koruma veya SESSION vb..)
- İlk madde de söyledim ama burdan yine fayda var söylemekte. Dışarıdan alınan verilerin mutlak suretle kontrolünü yapınız. Örneğin bir integer değer alıyorsanız bunu is_numeric() veya intval() gibi fonksiyonlardan geçirerek sql sorgularınıza dahil ediniz.
- String değerlerinize mutlak suretle sql sorgunuza dahil etmeden önce mysql_real_escape_string() veya addslashes() gibi fonksiyonlardan geçiriniz aksi halde php.ini de magic_quotest_gpc kapalı olduğu durumlarda sql injecktionlara elvermiş olursunuz.
- XSS veya html gibi zarar verecek kodlardan kurtulmak için strip_tags() veya htmlspecialchars() gibi fonksiyonlardan geçiriniz. Eğer bunlar sizi tatmin etmez ise html prufier sınıfını kullanabilirsiniz. Ayrıca strip_tags() kullanırken bazen bazı etiketlere izin vermek durumunda kalabiliriz örneğin <img> <a> bunlar ilk başta zararsız gibi görünse de <img src=”javascript:alert(document_cookie);”> gibi bir string ile aşılabilir o yüzden iyi bir filtreleme yapmanız gerekiyor.
- Diğer bir husus dosya upload konusu. Çoğu yeni programcı dosya tip kontrolünü basit bir mantık ile yapmaktalar Nedir bu yöntem hemen açıklayalım explode ile dosya adını nokta (.) karakterinden bölerek elde edilen dizinin birinci elemanının daima uzantı olacağı ihtimalini düşünmeleridir. Bu yanlış bir yöntemdir ve çok kolay aşılabilmektedir. Her dosya “dosya.uzanti” şeklinde olacak diye kural kaide yoktur. Örneğin şu şekilde olabilir exploit.jpg.php. Bu şekilde bir php dosyası az önceki bahsettiğim zayıf güvenlikten dolayı sunucuya upload edilebilmektedir. Çünkü nokta (.) dan bölünerek elde edilen dizinin birinci elamanı “jpg” olduğundan kolayca aşılacaktır ama asıl dosya uzantısı php idi. if ($dosya_tip == $uzanti[1])…
- Yönetici veya Kullanıcı oturumlarında eğer COOKIE kullanıyorsanız mutlak suretle COOKIE deki değerleri ilgili admin veya üye tablonuza sorgu yaparak COOKIE deki değerin doğruluğunu teyit ediniz. Bunu söylememin sebebi ise programcıların bazen basit hatalar yapmasından kaynaklanıyor. Örneğin bir cookie değeri atanır ve oturum kontrollerinde o çerez var ise geçiş izni verir. Saldırgan bu cookie değerini elde ettiği vakit sahte bir cookie yaratarak sizin sağlamış olduğunuz o güvenliği delip geçer. Hatta gerekirse kriptolayarak cookie değerleri atarsanız bir anahtar değeri ile güvenliğinizi daha da artırmış olursunuz.
- Gerekmediği Sürece COOKIE oturum yönetimi kullanmak yerine SESSION kullanabilirsiniz. Sebebine gelince COOKIE değerler ziyaretçilerin bilgisayarlarına kaydedildikleri için değişime uğrayabilme ihtimalinin olmasıdır.
Şuan aklımda bu saatte bunlar var ve paylaşayım dedim.


slm..
diyelim ki elimizde böyle bir script var.
kullanıcıdan alınan hiçbir veri kontrol edilmemiş.
örnek olarak database.php dosyası ile veritabanına bağlanılıyor ve her dosyada include ediliyor.
şimdi biz bu database.php dosasında bir filtreleme fonksiyonu oluşturup içine de stripslashes, htmlspecialchars, mysql_real_escape_string ve hatta preg_replace ile UNION tarzı sql kodlarını da değiştirecek bi kod yazsak güvenliğimiz ne derecede sağlanmış olur?
örnek kod: http://rapidshare.com/files/210199935/filtre.txt.html
(şu anda yazdım ve hiç denemedim. hatalı olabilir.)
Eğer kullanıcıdan alınan hiç bir veri kontrol edilmiyorsa illaki açık oluşturur sonuçta herkes formu düzgün doldurcak diye kural kaide yok. Ama veritabanına eklerken html leri süzerseniz escape vs uygularsanız halletmiş olursunuz.
işte ben de bu açık oluşturan veritabanına ekleme yapan kodları teker teker düzenleyip hepsine filtrele() fonksiyonunu eklemeden tek bir yerden güvenliği sağlayıp sağlayamayacağımız konusunda bilgi almak istemiştim..
teşekkürler..
array_map fonksiyonunu inceleyebilirsiniz. Örneğin POST Super Globaline strip_tags uygulamak için aşağıdaki yöntemi izleyebiliriz.
böylece $_POST içinde gelen tüm verilere strip_tags() fonksiyonunu uygulamış olursunuz ve sizin yazdığınız filtreleme fonksiyonundan daha hızlı çalışır php nin yerleşik fonksiyonu olduğu için.
evet array_map fonksiyonunu biliyorum ancak çok boyutlu dizilerde sanırım işe yaramayacak (yada nasıl yapılacağını ben bilmiyorum).
kullanıcıdan gelen veriyi üyelik formundan aldığımızı ve hobilerini sorduğumuzu farzedelim.
input type = “checkbox” name = “hobi[]” value = “yüzme”
input type = “checkbox” name = “hobi[]” value = “bisiklet”
input type = “checkbox” name = “hobi[]” value = “satranç”
bu şekilde bir veri gönderildiğinde array_map hobi dizisini bozuyor sanırım.
bunu engellemenin bir yolu bulunuyor mu acaba?
recursive bir fonksiyon yazıp array map içinde onuda çağırabilirsiniz.
array_map(‘fonksiyon_adi’,$dizi);
şeklinde kullanıcı tanımlı fonksiyonlarda kullanabilirsiniz.
Yusuf yine çok güzel bir döküman yazmışsın.
Tebrik ederim seni.
Yeni yazılarını dört gözle bekliyorum.
Güzel makale olmuş . Tabi yazı başlığındada yazdığı gibi bunlar script kodlarken güvenlik önlemleri . şimdi sadece bunları yaparak güvenliği script etkileşiminde sağlayabiliriz. İşin birde server tarafı var . Onuda artık başka bir yazısında bekleriz
emeğiniz için teşekkürler. çok faydalı oluyor..
benim de zaman zaman sıkıntı yaşadığım bir konuyu arkadaşlarla paylaşmak istiyorum. hepimiz yaşıyoruz ki; bazen saatlerce bilgisayar karşısında oturuyoruz. aslında kesinlikle unutmamız gereken güvenlik önlemlerini kafa yoğunluğundan dolayı yazmakta bulunduğumuz scriptimize dahil etmeyi unutabiliyoruz. herşeyi hafızada tutmamak ve birden fazla sitede çalışmak gibi durumlarla başa çıkacak bir program gereksinim vardı. mind manager bu konuda müthiş fayda sağladı. yapmış olduğum işlemlerde görsel olarak durum seviyesini belirtebiliyorum. unutmamam gereken yerleri not alıyorum ve daha bunun gibi ilerleyişle alakalı faydalı birçok yardımcı sistemleri var. güvenlik, seo, sayfa planlaması vs. not alıp, aşamaları bu not aldığımız soy ağacı tarzı görsel programda kısımların üzerlerine işaretleme imkanını buluyorum.
kısacası yazılımcı arkadaşların program arşivinde bulunması gereken bir program…
Harika bir makale olmuş.. Ellerinize sağlık..
$_POST = array_map(‘strip_tags’,$_POST);
bunu database.php içerisine eklersek sitede yapılan tüm post işlemler için güvenlik uygunlanmış mı oluyor tam anlayamadım bu kısmını?
@said
array_map tek boyutlu dizilerde işe yarıyor. Şöyle ki bir dizinin tüm elemanlarına strip_tags fonksiyonunu uyguluyor ama bu da yeterli değil sadece ufak bir önlem.