PHP Güvenliği I – OWASP Top 10 İncelemleri
Uzun süredir aklımda olan fakat bir türlü işten güçten fırsat bulamadığım bir yazı dizisine giriş yapmaya karar verdim. Aslında PHP güvenliği konusu bir çok sitede ( belkide yüzlerce site) işlenmesine rağmen halen güvenlik açıklarının genellikle çok basit yöntem ve metotların eksikliğinden kaynaklanması nedeniyle bende bu konuda yazan yüz bilmem kaçıncı kişi olmak istedim. Biraz da konuyu daha teatral/sunumsal tarzda anlatcağım.
PHP, çok güçlü bir script dili olmasının yanında ne yazık ki iyi bir şekilde kodlanmadığında başnızı ağrıtacak kadar beladır. Bu durum diğer tüm dillerde geçerli olsa da php’nin internet uygulamalarının neredeyse yarısından fazlasında kullanılması saldırılaaa karşı daha açık hale gelmesine neden oluyor.
Biraz kodlama ve işletim sistemi bilgisine sahip olan herkesin söylediği bir şey vardır “Linux ve Unix dünyanın en iyi sistemi, hacklenemez ,onunla herşeyi yaparsın..” şeklinde. Bu inanış ne yazık ki doğru değil. Bilgi güvenliğinde güvenlik kavramı “zincirin en zayıf halkası” kadar olarak tanımlanır. Yani siz düm düz bir unix, freebsd veya linux sürümünü bilgisayarınıza kurduğunuzda o sistem artık dünyanın en iyi korunan siteminin aksine en zayıf sistemi konumundadır. Aynı durum anti-virus yazılımı olmayan, firewall ayarlanmamış ve gerekli güvenlik policy leri tanımlanmamış tüm işletim sistemleri içinde geçerlidir…
Yazılım geliştirme sürecinden genellikle güvenlik kısmı en son düşünülmektedir. Bu şekilde bir yaklaşımın neticesinde gittikçe büyüyen kodlar içerisinde hangi bölümün nasıl bir güvenlik mekanizması ile korunacağına karar vermek gittikçe zorlaşmaktadır. İş hayatımda yapmış olduğum testlerde bir çok güvenlik çözümünün, kodlara, en son ve genellikle sisteme bir zarar verildikten sonra eklendiğini gördüm, fakat bu şekilde bir çözümde ancak ikinci bir sistem saldırısına kadar koruyucu olabilmiştir. Çünkü başta planlanmayan güvenlik çözümü sonradan kodlara dahil edilğininde başka sorunlara yol açmaktadır.
En çok yapılan hata ise Framework’lere fazlası ile güvenmek! Evet frameworkler gğvenlik açısından çok iyi altyapıya sahiptir ama tam anlamıyla framework fonksiyonlarını kullanıyorsanız. örnek olarak CodeIgniter framework’ünde çok gelişmiş filtreleme ve güvenlik modülleri olmasına rağmen halen çoğu kişi klasik GET POST yöntemini ve SQL cümleciklerini kulllanmakta ve CI’nın bu kodlarında güvenliğini sağladığına inanmaktadır….
Bu kadar lafı uzattıktana asıl konumuza gelelim. PHP güvenliği ile ne anlatacağız? Nelere değineceğiz?
İlk olarak her sene en yüksek 10 tehditi yayınlayan OWASP (Open Web Application Security Project)’in sıralamasına bakalım :
A1: Injection
A2: Cross-Site Scripting (XSS)
A3: Broken Authentication and Session Management
A4: Insecure Direct Object References
A5: Cross-Site Request Forgery (CSRF)
A6: Security Misconfiguration
A7: Insecure Cryptographic Storage
A8: Failure to Restrict URL Access
A9: Insufficient Transport Layer Protection
A10: Unvalidated Redirects and Forwards
buradan görüleceği gibi bir çoğu aslında verilerin doğru düzgün kontrol edilmemesinden kaynaklanan sorunlardır. Verilerin kontrol edilmemesinden kastımız nedir diyecek olursak bunu gerçek hayattan bir örnek ile açıklayalım.
Senaryo
Büyük bir fabrikanın kapısında güvenlik görevlisi bulunmakta. Güvenlik görevlisi kapıya gelen her misafir için öncelikle görüşülmek istenen kişinin ofisini arıyor ve gelen kişinin kendisi ile ilgisi olup olmadığını soruyor. Ofis çalışanı onaylar ise misafir kapıdan giriş yapabiliyor. Güvenlik görevlisi bu kişi ile ilgili bir kimlik kartı alıyor ve kendisine içeride kısıtlı alanlarda dolaşabileceğini gösteren bir yaka kartı veriyor. Bu kart sadece belli başı odaları açabilen bir sistem.
Büyük bir fabrikanın kapısında güvenlik görevlisi bulunmakta. Güvenlik görevlisi kapıya gelen her misafir için öncelikle görüşülmek istenen kişinin ofisini arıyor ve gelen kişinin kendisi ile ilgisi olup olmadığını soruyor. Ofis çalışanı onaylar ise misafir kapıdan giriş yapabiliyor. Güvenlik görevlisi bu kişi ile ilgili bir kimlik kartı alıyor ve kendisine içeride kısıtlı alanlarda dolaşabileceğini gösteren bir yaka kartı veriyor. Bu kart sadece belli başı odaları açabilen bir sistem.
Gerçek hayatta giriş kontrolü bu şekilde yapılıyor, yazılım tarafında ise aslında teorik olarak çok fazla bir farklı durum yok. En önemli fark burada kontrolü yapan insan ve anlık karar verebilme kabiliyetine sahip. Yani bekçi veya güvenlik görevlisi gelen kişinin davranışlarında bir tuhaflık sezer ise buna göre o kişiyi içeri almama şansına sahip. Yazılımsal süreçlerde ise bu yapay zekayı bizim kurmak zorunda olduğumuz. Yapay zekanınızı ne kadar iyi kodlarsınız güvenlik menizmanız da o kadar iyi işleyecektir. OWASP’ın sunmuş olduğu listede ise bu mekanizmanın hiç olmaması veya eksik olması nedeniyle ortaya çıkmış durumlar yer alıyor. Biz bu açıkları PHP, MYSQL, JAVASCRIPT ve HTML üzerinden ele alcağız. Yazılım Güvenliği yazı dizilerimizde ise DELPHI, PERL vb dillerde de ayrıca inceleyeceğiz.
A1: Injection (Araya Kod Girme)
Injection, herhangi bir veri giriş alanına/fonksiyona/paramtreye, aslında sistem tarafından düşünülmemiş veya planlanmamış bir kod parçacığının girilmesi ve bu kod parçasının çalıştırılmasına imkan sağlamak diyebilirz. Birçok injection çeşidi olmasına karşın en çok adı duyulan SQl Injection’dur. Saldırının başarılı olmasında en büyük etken sql için gönderilen query parametrelerinin kontrol edilmemesidir. Saldırgan, sql sorgusuna normalde planlanlanmamış zararlı bir parametre/kod parçasını araya sokarak sql ile ilgili işlemleri gerçekleştirebilir. Bu işlemler arasında tüm tablo yapısını almak, veritabanı yapsını öğrenmek, tablodaki tüm verilere değiştirme, silme veya ekleme işlemi yapabilmek, tüm veritabanını silmek gibi aklınıza gelebilecek her türlü sql işlemini araya kod girerek yapabilmektedir.
Bir örnek ile inceleyelim :
$musNo = $_POST['musteriNo']; //Müşteri bilgisi form aracılığı ile alınıyor!
$sql= "SELECT * FROM hesapBilgi WHERE musteriNo = ". $musNo;
$sorgu = mysql_query($sorgu);
Yukarıdaki sorgu örneğinde görüldüğü gibi formdan gelen müşteri no bilgisi hiçbir filtre ve kontrolden geçirilmeden sorguya dahil edilmiş. Tehlike de burada başlıyor. Saldırgan bu açığı keşfedebilmek için musteriNo bilgisini ” ‘ ” – tek tırnak – işareti ile değiştirrerek test ediyor. Eğer aşağıdaki gibi bir çıktı alıyor ise ;
Warning: You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near ' yayin_durumu = 'EVET' ORDER BY oto_id DESC LIMIT 0,20'
at line 1 in C:\Inetpub\vhosts\test_mysql.php on line 4
buaradan yola çıakrak sitemin sql injection açığına maruz bırakılabileceğini anlıyor ve sonrasında çeşitli yöntemler ile veritabanından bilgi almaya veya silmeye çalışıyor. SQL Injection ile ilgili komutların detaylı ve güzel bir çalışmasını Ferruh Mavituna’nın Cheat Sheet’inden görebilirsiniz : http://ferruh.mavituna.com/sql-injection-cheatsheet-oku/#Enablecmdshell
Korunma Yolları :
Bu tür saldırılardan korunmanın birçok yöntemi olmasına karşın en basit çözüm POST ve GET ile alınan bilgileirin mutlaka filtreden geçirilmiş olmasıdır. Birkaç basit fonksiyonu görelim.
Eğer sadece rakam veya sayısal değer okumak istiyorsak intval($veri); //Girilen karakterin sayısal değerini gösterir
MySQL için GET POST datası alıyorsak mysql_real_escape_string($veri); //Tüm zararlı kodları dönüştürür.
Normal verileri okuyarsak : htmlspeacialchars($veri) veya strip_tags($veri)
Injection sadece sql ile değil aynı zamanda kodlara da yapılabilmektedir. Buna en güzel örnek çok sık kullanılan index.php?sayfa=haberler şeklindeki sitelerde görülmektedir. Bu tür sitemlerde genellikle arka plandaki kod şu şekilde olmaktadır :
Burada ilk bakışta çok tehlikeli birşey görünmemekte, oysaki %00 (Null Byte Poision) açığı sayesinde sistem içerisindeki herhangi bir kod syafa olarak çağrılabilmektedir. Örnekde ben aşağıdaki çıktıyı aldım :
http://localhost/test.php?sayfa=cript.txt%00
Çıktısı :
EVIL HACKER! YAZI DOSYASI KODLAR VS:...
Normalde benim txt uzantılı bir dosyayı çağıramamam gerekiyordu! fakat Null Byte karakter sayesinde fonskyiona cript.txt den sonraki gelenleri önemsememesini söylemiş oldum…
Bu tür ataklardan korunmanın yoluda yine gelen bilgileri filtreden geçirerek zararlı bölmleri atmak. En basit yöntem ise :
str_replace(chr(0), '', $deger);
Özetle İlk sırada yer alan injection saldırılarından korunmak temel anlamda bu kadar kolay. Sizlere bir sürü karmaşık kod ve fonksiyon anlatmayacağım. Yukarıdaki basit çözümler ile en azından sitenize yapılacak 100 saldırının 98’ini bertaraf etmiş olacaksınız 🙂 Injection saldırılarını engellemeye yönelik bir çok hazır fonksiyon PHP içerisinde mevcut. HELP sayfasından bu fonksiyonları irdeleyebilirsiniz.
Yazımızın sonraki bölümü A2: Cross-Site Scripting (XSS) ile devam edecek, şimdilik bu kadar..
1 Comment
fatih uçar
Çok faydalı olmuş. Emeğinw sağlık. Bence bu seride yeni makaleler eklemelisin. Kolay gelsin