Pazartesi, Eylül 11. 2006 Bu makaleyi okuyan PHP kod yazarları; - XSS'in ne olduğunu, - Çerezlerin çalışma şeklini, - XSS'den rahatça nasıl korunabileceklerini öğrenecekler. XSS Nedir? XSS kısaca, HTML ve JavaScript yardımıyla bir sitede, siteye giren kullanıcıya tehlike arz edecek şekilde kod çalıştırmaya denir. Ziyaretçilerinizden bilgi almak amaçlı ya da onlara ait hesapları tekrar tekrar şifre girmeden kullanmaları için yollamış olduğunuz çerezleri -cookies- XSS yardımıyla çalabilirler ve kendilerini, sisteme o ziyaretçiymiş gibi gösterebilirler. Çerezler Nasıl Çalışır? Bir çerez, istemci -yani siz- tarafında herhangi bir bilgiyi, oturum numarasını vs. saklamaya yarayan ve sadece kendisinin yollandığı alan adı için bilgilerini veren bir araçtır denilebilir. Yani herhangi bir siteye girdiğinizde, karşı taraftan size bilgilerinizi tutmak için bir çerez yollanabilir. Kullanım alanları, genel olarak kullanıcı bilgileri ya da sizin karşı taraftaki oturum numaranızı karşılaştırmak içindir. Bu noktada, karşı tarafın, sizin diğer çerezlerinizin içindeki bilgileri ele geçirmenizden şüphe edebilirsiniz belki; ancak başta da bahsettiğimiz gibi, tarayıcılar sadece çerezi isteyen yerin alan adı ve dosya yolu uyuşuyorsa bu bilgileri yollarlar, olağanüstü bir durum dışında bu bir güvenlik sorununa yol açmaz XSS Nasıl Çalışır? Bu yazının tehlikeli işler yapmaya meyilli olan kişiler tarafından da okunma ihitmali olduğu için açık açık anlatım yoluna gitmeyi düşünmüyorum Şöyle bir gözden geçirecek olursak; JavaScript dilinde çerezleri yönetmeyi sağlayan bir cookie yöntemi bulunmaktadır. Bu yöntem yardımıyla sayfaya ait olan çerezler alınıp, okunabilir ve değiştirilebilir. XSS açıklarından yararlanan kötü niyetli kişiler de, JavaScript'in bu özelliğinden yararlanarak sayfayı gezen kullanıcının çerez bilgilerini alıp, kendilerininkiyle değiştirmeye çalışırlar. Bu nedenle XSS açığı bulunan herhangi bir sayfayı gezen ziyaretçinin, eğer ilgili sayfadan bir hesabı da varsa çok dikkatli olması gerekmektedir; bunun yanında site sahiplerinin de bu konuda ciddi şekilde önlem almaları, olayların patlak vermesini de engeller. Çözüm yollarına birazdan değineceğiz... PHP'nin yeni sürümleriyle beraber gelen, HTTP başlıklarındaki Set-Cookie özelliğine eklenecek olan bir HttpOnly deyimiyle, tarayıcılar deyimin geçtiği çerezi JavaScript yoluyla almayacak/göstermeyecektir... Şimdi bu saldırılardan nasıl korunulacağımızı öğrenelim... Koruma Yolları Nelerdir? Yukarıda bahsettiğimiz XSS saldırılarından iyi bir şekilde korunabilmek için, öncelikle kullanıcı tarafından gelen bilgileri nasıl filtreleyebileceğimizi düşünelim... Çerez çalmak için gerekli olan kodun çalıştırılması için, öncelikle <script></script> etiketleri arasına yazılması gerekir ki, buradan HTML etiklerinde kullanılması zorulu olan < ve > karakterlerini düzgünce filtrelemenin, sorunumuzun büyük bir kısmı çözebileceğimiz anlamına gelir. O halde: <?php htmlentities ; // htmlentities fonksiyonu, kendisine parametre olarak // konulmuş verinin içindeki <, >, & gibi karakterleri // '<', '>' gibi pratikte zararsız, HTML sayfada ise // normal görünecek karakter gruplarıyla değiştirir. // Daha fazla koruma için ikinci parametre olarak // 'ENT_QUOTES' diyebilir ve tırnak işaretlerini de // filtreleyebiliriz... // ?> gibi birşeyler yapalım Peki sadece bu tek fonksiyon yeterli olabilir mi? Aslında, hayır... URL adresinden yollanacak olan bilgiler, herhangi bir ASCII karakterinin onaltılık formatında da olabileceği için (örn. boşluk için %20 gibi) bu işlemi atlatabilir. İşimizi sağlama almak için, URL'den gelen ASCII formatındaki bilgiler de dahil olmak üzere, gönderilen veriyi normal haline getiren urldecode fonksiyonunu kullanabiliriz: <?php htmlentities(urldecode ; ?> Peki bu yeterli mi? Bazen, verinin kullanıldığı yere göre, farklı filtrelemeler yapmamız gerekebilir. Bu tür filtrelemeler için quotemeta ve addslashes fonksiyonları biçilmiş kaftandır. Tüm bunları göz önüne alarak, aşağıdaki gibi bir fonksiyon yazalım: . \ + ? karakterlerinin önüne \ karakteri koyar. Tırnak işaretinin önüne \ karakteri koyar. <?php function dataFilter($data, $mod = 1, $op = 0) { // Öntanımlı fonksiyon çalışma düzeyini 1, seçeneği 0 olarak ayarladık. $data = urldecode ; // Güvenli filtreleme için URL'den gelen veriyi çözdük. if($mod 0) else if($mod 1) else if($data 2) else if($mod 3) } ?> Yukarıdaki fonksiyonu daha genel bir şekilde yazının devamında kullanacağız, ancak ondan önce kullanımı hakkında kısa birkaç örnek; - dataFilter($veri, 1): $veri değişkenine htmlentities uygulanır. Ortalama bir filtreleme. - dataFilter($veri, 2, 2): Tırnakların da htmlentities ile filtrelendiği, quotemeta 'nın kullanıldığı bir düzey seçeneği... Çok fazla karakter filtrelediği için her veride kullanmanız sorun çıkarabilir. - dataFilter($veri, 3, 3): Bahsettiğimiz tüm fonksiyonların kullanıldığı paranoyakça bir filtreleme Çok fazla gerek duyucağınızı sanmıyorum, genelde sorun çıkarır hepsi bir arada olunca Kullanıcıdan Alınan $_POST ve $_GET Dizileri Yazımızın bu son kısımında, hem yukarıda yazdığımız işe yarar ama çok karışık -kim ezberler ki zaten? - fonksiyonumuzu kullanabileceğimiz, hem de kullanıcıdan gelen iki önemli diziyi nasıl filtreleyeceğimizi göstereceğiz... O halde; - Bu iki sabit diziyi dataFilter fonksiyonumuzun htmlentities ve addslashes fonksiyonlarının kullanıldığı çalışma düzeyinde filtreleyelim ve - $_POSTS, $_GETS isimlerinde filtrelenmiş veriyi saklayan bir dizi oluşturalım: <?php $_GETS = array ; $_POSTS = array ; foreach foreach ?> Alıntı ve Ögrentidir... Bana Çok Lazım Oldu...