Developersland

Teknoloji ve Yazılım Blogu

  • Yazıtipi boyutunu arttır
  • Varsayılan yazıtipi boyutu
  • Yazıtipi boyutunu azaltır

PHP - Güvenlik Sağlamak Amacıyla Kullanıcıdan Alınan Verilerin Kontrolü (Sql Injection Önleme)

Php Güvenlik

Kullanıcıdan bir veri aldığımızda sistemimizi saldırılara açık hale getirmiş oluruz. Bu nedenle kullanıcıdan alınan verilerin güvenliğimizi tehdit etmeyecek biçime sokulması gerekmektedir. SELECT * FROM users WHERE username = ' $kullaniciAdi ';
SELECT * FROM users WHERE username = '' OR '1'='1';
' or '1'='1' -- '
' or '1'='1' ({ '
' or '1'='1' /* '

Eğer kullanıcıdan alınan veri bir sql sorgusu içerisinde kullanılacaksa bunun farkında olan kötü niyetli kişiler "SQL ENJECTION" yöntemini kullanarak girdikleri input'a sql cümlecikleri ekleyerek veritabanımız üzerinde işlemler gerçekleştirebilir. Sql Injection ile ilgili ayrıntılı bilgiye buradan ulaşabilirsiniz.

Kısaca örnek vermek gerekirse, aşağıdaki gibi bir sorgunuz olduğunu düşünelim.




Burada kullanıcı adı kullanıcıdan alınan bir input ise kullanıcı oraya ' or '1'='1 şeklinde bir cümlecik girerek WHERE den sonraki kısmın TRUE olmasını sağlayabilir. Sorgunuz aşağıdaki gibi olacaktır:



Kötü niyetli kullanıcı ayrıca aşağıdaki gibi cümlecikler girerek sizin yazdığınız query'nin kalan kısımlarının yorum satırına dönüştürülmesini sağlayabilir.



Peki bu tarz güvenlik açıkları vermemek için neler yapmalıyız?

Bunun için aşağıdaki gibi bir fonksiyona ihtiyacımız olacaktır. kullanıcıdan aldığımız ve sorgularda kullanacağımız tüm veriler bu fonksiyona sokularak güvenli bir biçime sokulmalıdır.


function sqlEscape($data){

    if(get_magic_quotes_gpc()){

        $data = stripslashes($data);

    }

    $data = mysql_real_escape_string($data);

    return $data;

}

Bu fonksiyon öncelikle sunucuda magic quotes gpc özelliğinin açık olup olmadığını kontrol eder. Eğer sunucuda bu özellik açık ise sunucu otomatik olarak kullanıcıdan aldığı verilerde bulunan tırnak işaretlerinin önüne ters slash işareti (\) koyar. bu nedenle öncelikle sunucuda bu özelliğin açık olması durumunda bu \ işaretlerini stripsplashes fonksiyonu vasıtasıyla yok ederiz. stripsplashes php'nin kendi fonksiyonlarından biridir ve verilen bir stringdeki bütün \ işaretlerini yok ederek bize yeni halini geri döndürür. 

Daha sonra kullanıcıdan alınan input mysql_real_escape_string fonksiyonuna sokularak bir sql cümleciği içerisinde güvenle kullanılabilecek biçime sokulmuş olur. mysql_real_escape_string aşağıda sıralanmış özel karakterlerin önüne \ koyarak bunların özel anlamlarını kaybetmesini sağlar.


\x00

\n

\r

\

'

"

\x1a


Veritabanına yazılan herşey filtrelenerek yazılmalıdır. Veritabanından çekilen herşey escape edilmelidir.


Veritabanından bilgilerin çalınması durumunda veya kötü niyetli çalışanların bir kullanıcnın şifresini bulmak için veritabanına baktığı durumlarda şifrenin anlaşılmaması amacıyla

şifreleri veritabanına kaydederken md5 fonksiyonundan geçirerek kaydetmek çok iyi bir güvenlik önlemiydi eskiden, ama artık değil çünkü md5 algoritmasının çözülebileceği kanıtlanmış durumdadır. Bunun bir örneğini buradan görebilirsiniz: http://md5.rednoize.com/

Aşağıda gösterilen yöntem saldırganın işini biraz zorlaştıracaktır.


<?php

$salt = 'Birstring';

$password_hash = md5($salt . md5($_POST['password'] .$salt));

?>


Eğer sistemimiz müşterilerin kredi kartı bilgisi gibi bilgilerini veritabanında kayıtlı tutacaksa bu bilgilerin kriptografik algoritmalarla şifrelenmesi lazım.



NOT: magic quotes özelliğinin açık olması durumunda, stripsplashes fonksiyonunu kullanmadığımız taktirde tırnak işaretlerinin önüne iki (\\) slash koyulmasına neden olurduk.

Magic Quotes ile ilgili burada arkadaşımız çok güzel anlatmış.



KAYNAKLAR

http://en.wikipedia.org/wiki/SQL_injection

http://php.net/manual/en/function.mysql-real-escape-string.php

 

Yorumlar  

 
0 #1 Evrim Altay Koluaçık 22-01-2013 08:06
Verdiğiniz site veritabanında ki kayıtlar ile girdiğimiz kodu eşliyor. Bu da sadece belirli kelimeleri bulabileceği anlamına geliyor.
12345
admin
gibi şifreleri kolayca bulur ama ben altay yazıp md5e çevirip denediğimde :) sonuç hüsran :)

md5 çözülememiştir. Eğer huylanıyorsanız , bunu deneyin;
$sifre = "admin";
$guvenli_sifre = md5(md5($sifre) );

iki, üç veya dört kez md5'den geçirin. Veritabanı bile kurtaramaz :)
Alıntı
 

Yorum ekle


Güvenlik kodu
Yenile