Header Ads

Haberler Haberler
Flaş Haber
recent

Php ile Güvenlik - SQL Injection

php güvenlik
Php'de kod yazanlar bilir. Biraz programlama bilgisi olan herkes php'yi de yakın zamanda kavrayabilir fakat unuttuğumuz bir şeyler var oda güvenlik işte. Ben de bu yazı dizisinde php'de güvenlik için alınacak önlemlere değineceğim ve ilk yazımda SQL Injection'dan bahsedeceğim.


Bu işlem yapılırken oluşan açık ile veritabında istenilmeycek değişiklikler yapılabilir. Diyelim bir kullanıcı tablomuz olsun ve üye girişi yapılmaya çalışılsın.

$k_adi = $_POST['k_adi'];
$sifre = $_POST['sifre'];
$sorgu = mysql_query("SELECT count(id) FROM kullanicilar WHERE k_adi='$k_adi' AND sifre='$sifre';"); 
Yukarıda görüldüğü gibi formdan gelen verileri direkt sorguya yerleştirdik ve k_adi ve sifre kontrolü yaptırdık.

Ancak bazı art niyetlik kişiler k_adi  (kullanıcı adı) alanına ' or 1=1 --  ve sifre (şifre) alanına da ajkshdkjah gibi rastgele karakter girerler sebebi boş bırakma hatası almamak için. Bu şekilde girildikten sonra kodumuz şu şekli alacaktır.
$sorgu = mysql_query("SELECT count(id) FROM kullanicilar WHERE k_adi='' or 1=1 --' AND sifre='ajkshdkjah'");
Sorgumuzda gördüğünüz -- işaretinden sonraki gelen komut satırlarını yorum olarak algılar ve çalışmazlar. O yüzden şifre kontrolüde yapılmamış olur. Zaten orada da or 1=1 ile de sql komutunu doğrulamış olduk. Peki nasıl doğruladı derseniz. Genelde kullanıcılar tablosunda 1. satırda admin kayıtlıdur bu şekilde de ilk satırı aldı ve admin olarak giriş yapılmış olundu. Yani siteniz hacklendi diyebiliriz.

Bu sorundan kurtulmak isterseniz ço kolay bir yolu var verilerinizi escape etmek yani gelen '," (tek tırnak veya çift tırnak) gibi verilerin işlenmemesini sağlamak. Bunu için bize php'nin sağlamış olduğu mysql_real_escape_string fonksiyonu vardır. Şimdi bu fonksiyonu kullanarak kodlarımızı yeniden yazalım.
$k_adi = mysql_real_escape_string($_POST['k_adi']);
$sifre = mysql_real_escape_string($_POST['sifre']);
$sorgu = mysql_query("SELECT count(id) FROM kullanicilar WHERE k_adi='$k_adi' AND sifre='$sifre';"); 
Şimdi dışardan gelen verileri temizlemiş olduk ve saldırı oldu ise kodlarımız nasıl bir hal alacaktır ona bakalım.
$sorgu = mysql_query("SELECT count(id) FROM kullanicilar WHERE k_adi='\' or 1=1 --' AND sifre='ajkshdkjah'");
 Görüldüğü gibi ' (tek tırnak) verisini \' şekline getirerek işletmedik sanki String veri gibi algıladı ve sorun ortadan kalkmış oldu.

Buraya kadar sadece STRING verilerden gelen SQL Injection saldırılarından kurtulabiliriz. Peki biz sayılarlar uğraşıyorsak nasıl kurtulabiliriz bu durumdan hemen onada bir çözüm getirelim.ü
http://www.siteadi.com/index.php?id=123
Örnek olarak şöyle bir yerden veri almış olalım. Yukarıdaki id değerini almak için ise.
$id  = $_GET['id'];
Bu şekilde kodumuzu kullanırsak yine aynı saldırılara mağruz kalırız o yüzden kodumuzu şu şekilde değiştirmeliyiz.
$id  = intval($_GET['id']);
$id  = str_replace("-","",$id);
Sayılar (Integer) alanını sorgulayacağımız için intval ile integer validasyon etmiş oluyoruz.Yani GET ile gelen verimiz "123asd" ise, intval sayesinde "123" oluyor.Yani fonksiyonumuz ilk karakterden itibaren tek tek her karakteri sona kadar inceliyor gelen veriyi ve eğer ilk karakter herhangi bir rakam ise, yani 123 gibi başlıyorsa, döngüye devam ediyor, ama asd gibi string türe denk geliyorsa orada döngü break; olup sonlanıyor ve bize soldan itibaren aldığı rakamları veriyor. Eğer ilk karakter string olsaydı, o zaman da döngüden geri gelen değer 0 oluyor.

Başlarına - gibi karakterler koyarak, mysql de - integer türü id incelemeye kalkıyor ve hata verdiriyor. O yüzden - karakterlerini de replace etmekte fayda var.

Dışardan gelen veriler ile sorgulama yapıyorsanız mutlaka ama mutlaka (cookie, session, get, post gibi yollarala) gelen verileri temizlemelisiniz.

Şimdilik sadece SQL Injection'dan kurtulma yönetminden bahsettik. Bunun dahası da var bir sonraki yazımda da diğer bir güvenlik yöntemi olan RFI - LFI (Remote File Include - Local File Include) Açığından Kurtulma yollarından bahsedeceğim.


2 yorum:

  1. Gayet faydalı bir yazı olmuş elinize sağlık. RFI konusunu beklemedeyim.

    YanıtlaSil
  2. Merhabalar hocam çok güzel anlatmışsınız ben bu tarz yapıyordum gelen Getlerin kontrolunu acaba bu nasıldır.

    $ID = mysql_real_escape_string($_GET['ID']);

    YanıtlaSil

Blogger tarafından desteklenmektedir.