Güvenli PHP Uygulamaları – Kullanıcı Girdilerinin Filtrelenmesi

Kullanıcı girdilerine güvenilmemeli, betiklerimizin güvenliği için
tüm girdiler filtrelenmelidir.

Örneğin kullanıcıdan yaş bilgisini isteyelim:

Kullanıcıdan beklenen girdi, sayı türünde bir değerdir.
Aşağıdaki kod bu doğrulamayı yapar.

$sonuc = preg_match("/[0-9]{1,3}/",$_POST['yas']);
if($sonuc === true)
echo "Girdi doğrulandı";
else
echo "Girdi sayı değil";

Kullanıcının hayat hikayesini istediğimizi varsayalım, yukardaki gibi bir basit bir doğrulama yapamayız, bunun yerine php nin bize sunduğu temel filtreleme işlevlerinden yararlanabiliriz.
Html tagları sorunlara yol açabilir.
stript_tags() işlevi html etiketlerini yok eder.

$girdi = "<h1>büyük bi başlık</h1><span>span etiketi</span>";
echo strip_tags($girdi);

Yukardaki örneğin çıktısı:

büyük bi başlık span etiketi

Bazı etiketlere izin vermek istiyorsak:

$girdi = "<h1>büyük bi başlık</h1><span>span etiketi</span>";
echo strip_tags($girdi,"<span>");</span>

Yukardaki örneğin çıktısı:

büyük bi başlık <span>span etiketi</span>

htmlentities() işlevi tüm html karakterlerini html entitilerine çevirir.

$girdi = "<h1>büyük bi başlık</h1>";
echo htmlentities($girdi, ENT_QUOTES,'UTF-8');

yukarıdaki örneğin çıktısı:

&lt;h1&gt;büyük bi başlık&lt;h1&gt;

Javascript Hatası:…submit is not a function

Javascripteki ayrılmış kelimeler(reserved words), button ismi ve fonksiyon olarak kullanıldığında çatışma(collision) meydana geliyor.

Hata Mesajı:

1
this.form.submit is not a function

“Submit” metodunu kullandığım yer:

1
<select  onchange="this.form.submit();">

Buton adı olarak “submit” kulladığım yer:

1
<input type="submit" name="submit" value="Ekle">

Buton adını “submit”ten başka bir adla, örneğin “ekle” olarak değiştirdiğimde sorun düzeliyor.

1
<input type="submit" name="ekle"  value="Ekle">

Güvenli PHP Uygulamaları-Sql enjektelerine karşı önlemler

Veritabanına gönderilen her bir değişken mysql_real_escape_string()
işlevinden geçirilerek sql enjeksiyonlarına karşı önlem alınabilir.
Bu işlev veritabanları için özel anlamı olan karakterleri escape-kurtarma işlemine tabii tutar,
bu karakterlerden bazıları: \n, \r, \, ‘, ”

Aşağıdaki gibi kullanıcı adı ve şifre alanlarından oluşan bir giriş formumuz olsun:

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>mysql_real_escape_string</title>
</head>
<body>
<form name="form1" action="" method="post">
Kullanıcı adı:<input type="text" name="kullanici_adi" value="" /> <br />
Şifre<input type="password" name="sifre" value="" /> <br />
<input type="submit" value="gönder" name="gonder" /></div>
</body>
</html>

Kullanıcının formdan aşağıdaki bilgileri gönderdiğini varsayalım.

1
2
$_POST['kullanici_adi'] = 'zihni';
$_POST['sifre'] = "' OR ''='";

Kullanıci adi ve sifre verilerinin veritabanında olup olmadığını kontrol edelim

1
2
3
4
5
6
7
8
<?php
$sorgu = "SELECT * FROM kullanicilar
WHERE kullanici_adi='{$_POST['kullanici_adi']}' AND sifre='{$_POST['sifre']}'";
 
$sonuc = mysql_query($sorgu) or die(mysql_error());
$satir = mysql_fetch_array($sonuc);
echo $satir['kullanici_adi'];
?>

mysql’e gönderilen sorgu aşağıdaki gibi olur:

1
SELECT * FROM kullanicilar WHERE kullanici_adi='zihni' AND sifre='' OR ''=''

Görüldüğü gibi sifre geçersiz olsa bile sorgu sonucu başarılı olur.

Eğer formdan gelen bilgileri mysql_real_escape_string() işlevinden geçirdikten sonra veritabanına gönderirsek:

1
2
3
4
5
6
7
8
9
10
11
<?php
$sorgu = sprintf("SELECT * FROM kullanicilar
WHERE kullanici_adi='%s' AND sifre='%s'",
mysql_real_escape_string($_POST['kullanici_adi']),
mysql_real_escape_string($_POST['sifre']) );
 
$sonuc = mysql_query($sorgu) or die(mysql_error());
$satir = mysql_fetch_array($sonuc);
echo $satir['kullanici_adi'];
echo $sorgu;
?>

mysql’e gönderilen sorgu aşağıdaki gibi olur ve bir sonuç döndürmez.

1
SELECT * FROM kullanicilar WHERE kullanici_adi='zihni' AND sifre='\' OR \'\'=\''

Türkçe Tarih Biçimleme

Örneğin, aşağıdaki gibi mysql Date türünde bir stringimiz olsun.

2009-06-20

Bunu aşağıdaki biçimde göstermek isteyelim.

20 Haziran 2009 , Cumartesi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function tarihBicimle($girdi)
{
	global $aylar,$gunler;
	preg_match("/([0-9]{4})-([0-9]{2})-([0-9]{2})/",$girdi,$eslesme);
	$yil = $eslesme[1];
	$ay = intval($eslesme[2]);
	$gun = $eslesme[3];
	$gunMetin = $gunler[date("w",mktime(0,0,0,$ay,$gun,$yil))];
	$tarih=$gun.' '.$aylar[$ay].' '.$yil .' , '.$gunMetin;
	return $tarih;
}
 
$aylar = array(1=>"Ocak",2=>"Şubat",3=>"Mart",4=>"Nisan",5=>"Mayıs",6=>"Haziran",7=>"Temmuz",8=>"Ağustos",9=>"Eylül",10=>"Ekim",11=>"Kasım",12=>"Aralık");
 
$gunler = array(0=>"Pazar",1=>"Pazartesi",2=>"Salı",3=>"Çarşamba",4=>"Perşembe",5=>"Cuma",6=>"Cumartesi");
 
echo tarihBicimle("2009-06-20");
 
Çıktı:
20 Haziran 2009 , Cumartesi

PHP İle Bütün Çerezleri(Cookie) Silme

İstemci bilgisayarda sakladığımız çerezler, $_COOKIE süper küreseline atanırlar.
Aşağıdaki kod, tüm çerezleri getirir, sonrasında çerezin değerini boş dizge ve geçerlilik süresini geçmişe ayarlayarak siliyoruz.

1
2
3
4
5
<?php
foreach ($_COOKIE as $isim => $deger){
setcookie($isim,"",time()-60*60*24, "/", ".zihni.net");
}
?>