THT DUYURU

Web & Server Güvenliği Doğru web ve veritabanı sunucusu güvenliği sağlanmadan, bilgisayar korsanları hassas verilerinize erişebilir. Web, Sunucu ve veritabanı güvenliğini nasıl sağlayacağınızı buradan öğrenebilirsiniz.

Seçenekler

PHP’de XSS Saldırıları ve Korunma Yolları

Black-Box - ait Kullanıcı Resmi (Avatar)
Emektar
Üyelik tarihi:
07/2008
Nereden:
İstanbul.
Mesajlar:
5.237
Konular:
2649
Teşekkür (Etti):
254
Teşekkür (Aldı):
1983
Ticaret:
(0) %
03-12-2010 01:01
#1
PHP’de XSS Saldırıları ve Korunma Yolları
Bu makaleyi okuyan PHP kod yazarları;
- XSS’in ne olduğunu,
- Çerezlerin (cookie) çalışma şeklini,
- XSS’den rahatça nasıl korunabileceklerini öğrenecekler.

XSS Nedir?
XSS (Cross Site Scripting - Çapraz Kod Çalıştırma) 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ı (domain) 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. (Eğer tarayıcınızın güvenlik ayarları çok sıkı değilse, otomatik olarak kabul ediecektir bu çerezler )

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 (örn. www.foo.com/hede adresine ayarlı bir çerez, asla www.foo.com/hodo adresine yollanmaz) 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. (yani; ********.cookie) Bu yöntem yardımıyla sayfaya ait olan çerezler alınıp, okunabilir ve değiştirilebilir. [1] 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...

[1] 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 (Forum Kurallarını Okuyun)(Forum Kurallarını Okuyun) etiketleri (tags) 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 hâlde:



Kod:
<?php
htmlentities($xss_potansiyelli _veri);
// 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...
// (bkz. php.net/htmlentities)
?>



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 (hexadecimal) 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 hâline getiren urldecode() fonksiyonunu kullanabiliriz:



Kod:
<?php
htmlentities(urldecode($xss_po tansiyelli_veri));
?>




Peki bu yeterli mi? Bazen, verinin kullanıldığı yere göre, farklı filtrelemeler yapmamız gerekebilir. Bu tür filtrelemeler için quote****() [2] ve addslashes() [3] fonksiyonları biçilmiş kaftandır. Tüm bunları göz önüne alarak, aşağıdaki gibi bir fonksiyon yazalım:

[2] . \\ + * ? [ ^ ] ( $ ) karakterlerinin önüne \\ (backslash) karakteri koyar.
[3] Tırnak işaretinin önüne \\ karakteri koyar.



Kod:
<?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($data);
// Güvenli filtreleme için URL’den gelen veriyi çözdük.

if($mod == 0) {
// Düzey 0 ise; sadece çözülmüş hâlini döndür:
return $data;
} else if($mod == 1) {
// Düzey 1 ise; htmlentities() uygulanmış hâlini döndür,
// Seçenek 1 ise; fonksiyonun tırnakları da filtrelemesini sağla:
return ($op == 0) ? htmlentities($data) : htmlentities($data, ENT_QUOTES);
} else if($data == 2) {
// Düzey 2 ise; sadece quote****() uygulanmış hâlini döndür,
// Seçenek 1 ise; htmlentities()’i de ekle,
// Seçenek 2 ise; tırnakları da filtrele:
return ($op == 0) ? quote****($data) :
(($op == 2) ? htmlentities(quote****($data), ENT_QUOTES) : htmlentities(quote****($data)) );
} else if($mod == 3) {
// Düzey 3 ise; addslashes() uygulanmış hâlini döndür,
// Seçenek 1 ise; addslashes()’***uote****() fonksiyonunu da ekle,
// Seçenek 2 ise; seçeneksiz duruma htmlentities() fonksiyonunu ekle,
// Seçenek 3 ise; 1. seçeneğe htmlentities() fonksiyonunu ekle:
if($op == 0)
return addslashes($data);
else if($op == 1)
return addslashes(quote****($data));
else if($op == 2)
return htmlentities(addslashes($data) );
else if($op == 3)
return htmlentities(addslashes(quotem eta($data)));
}
}
?>




(Bu fonksiyonda bahsettiğimiz bilgilere bir de çalışma düzeyi ekleyerek hepsini bir arada kullanmayı amaçladım, daha farklı alanlarda tek fonksiyonla idare edilebilsin diye )
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, quote****()’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 hâlde;
- 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:



Kod:
<?php
$_GETS = array();
$_POSTS = array();

foreach($_GET as $key => $value) {
$_GETS[$key] = dataFilter($value, 3, 2);
}

foreach($_POST as $key => $value) {
$_POSTS[$key] = dataFilter($value, 3, 2);
zeus49 Teşekkür etti.

Bookmarks


« Önceki Konu | Sonraki Konu »
Seçenekler