SQL’de Kabus, SQL Injection!

Php | | 25 Eylül 2008

Merhaba t-infection okurları, bu sitedeki ilk yazımda, PHP’ye ilk başladığım zamanlar en çok yaptığım bir hatayı ve bunu nasıl düzelteceğimizi anlatmak istedim. Eğer PHP yazıyorsanız, ilk başta öğrenmeniz gereken önemli noktalardan birisidir, aksi taktirde bütün emekleriniz boşa gidebilir.

SQL injection denen method ile, veritabanınıza yetkisiz işlem yaptırılabilir. Bu yetkisiz işlemler ile, veritabanınızdaki bir tablo tamamen boşaltılabilir, veriler silinebilir veya veri eklenebilir, daha da kötüsü yazdığınız script bir yönetim paneline sahipse buraya izinsiz girişler olabilir.

SQL injection methodları farklılık gösterebilir, URL ile yapılabilir(GET), sitedeki formlar ile yapılabilir(POST). Temel mantığı ise, sizin yazdığınız SQL sorgularını safdışı bırakarak çalıştırılmak istenen sorguların çalıştırılmasıdır. Burada bu methodları tabi ki anlatmayacağım, bunun yerine PHP’de SQL injection’a karşı nasıl önlemler alabileceğimizi anlatacağım.

Basit bir SQL sorgumuz olsun, url ile gelen id’ye sahip makaleyi veritabanından seçelim.

$query = mysql_query("SELECT * FROM makaleler WHERE id=$_GET['id']", $baglanti);

Bu şekilde kullandığınızda, çok büyük bir tehlike içerisindesiniz demektir. Bu sorguyu güvenli hale getirmek için sprintf fonksiyonunu da kullanacağız(bunu sadece daha düzenli bir kod yazımı için kullanıyoruz) ve sorgumuzu aşağıdaki hale getireceğiz:

$id = $_GET['id'];
$id = get_magic_quotes_gpc() ? stripslashes($id) : $id;
$id= function_exists("mysql_real_escape_string") ? mysql_real_escape_string($id) : mysql_escape_string($id);
$query = mysql_query(sprintf("SELECT * FROM makaleler WHERE id='%s'", $id), $baglanti);

Sorgumuzu buhale getirerek kimsenin SQL’imize dokunmamasını sağlamış oluyoruz.

Bir örnek daha vermek gerekirse;

$query = mysql_query("INSERT INTO makaleler(baslik, icerik, yazan) VALUES ($_POST['baslik'], $_POST['icerik'], $_POST['yazan'])", $baglanti);

yerine;

function guvenliyap($value) { // kullandığımız kodları fonksiyon haline getirelim
$value = get_magic_quotes_gpc() ? stripslashes($value) : $value;
$value= function_exists("mysql_real_escape_string") ? mysql_real_escape_string($value) : mysql_escape_string($value);
return $value;
}

$query = mysql_query(sprintf("INSERT INTO makaleler(baslik, icerik, yazan) VALUES ('%s', '%s', '%s')", guvenliyap($_POST['baslik']), guvenliyap($_POST['icerik']), guvenliyap($_POST['yazan'])), $baglanti);

kullanarak güvenliğimizi sağlamış oluyoruz.

Kısacası, URL veya POST ile gelen bütün verileri bir filtreden geçirerek, bu gelen verinin içinde bulunabilecek ‘ işaretlerini \’ haline getiriyoruz. Böylece bu gelen verilerdeki zararlı işaretler, sorgumuzun içine karışmıyor ve SQL injection ile sitemize zarar vermek isteyen kişiler avuçlarını yalıyorlar.

Rastgele Yazılar

Bu yazı , , kelimeleriyle etiketlenmiştir. Bu yazıyı beğendiyseniz Delicious, Twitter, Facebook gibi sitelerde paylaşabilirsiniz. Yazılarımızı düzenli olarak takip etmek içinse Rss abonemiz olabilirsiniz.

SQL’de Kabus, SQL Injection! yazısı için 9 yorum yapılmış...

  1. omer abul diyor ki:

    merhabalar.. Gercekten bu sql injection basa bella bi acik… Ama Replace ile gereken komutları kapatabılır.. php de arkadasımın biri sole bi acık oldugunu solemisti bana..

    ” cift tirnak acigi.. ama nasıl kullanıldıgı hakkında bir bilgi alamadım..

  2. Bartuc diyor ki:

    Bu bahsedilen çift tırnak açığı denen olay da sql injection’un bir türü. Bu verdiğim güvenlik kodları/fonksiyonu ile hiç bir şekilde SQL injection’a maruz kalmazsınız, kökten çözüm budur.

  3. Aistlinri diyor ki:

    çift tırnak açığı sadece PHP’nin değil bir dönem ASP’nin de baş belası olmuştu. Ancak bir konuda daha detaylı bir açıklama rica etmekteyim kullandığın değerleri ve kodların açılımlarını yaparsan bizde neyin neye yaradığını daha iyi öğreniriz diye düşünüyorum.

  4. Bartuc diyor ki:

    Bu kodlarla tam olarak yaptığımız şey, kullanııcıdan url veya post yoluyla gelen bütün verileri mysql sorgusunda kullanmadan önce filtrelemek, ‘ işareti kullanarak gelen verinin sorguya karıştırılmasını engellemek. Bu şekilde kullandığımızda gelen verideki ‘ işareti \’ halini alır ve bu sayede kötü niyetli kişiler amaçlarına ulaşamazlar.

  5. Ahmet Eyüp diyor ki:

    İşe yarar bir yazı olmuş, paylaştığın için teşekkürler Cihan. Yalnız kodları renklendirebilirsen daha güzel olur. Okunabilirliği zayıf çünkü.

    İlk yazın hayırlı olsun, çalışmalarında başarılar ;)

  6. Suphi diyor ki:

    yanlış hatırlamıyorsam eğer vakti zamanında microsoft sql server’da çıkmıştı bu tarzda sql injection açıkları.

    ‘ işareti kullanılarak izinsiz komut işletiliyordu.

    (‘ or 1=1– gibi)

    bu tarz işlemlerle kullanıcı adı/parola sorgulamalarından true sonuç döndürülüyordu.

  7. asd diyor ki:

    bunlar korumaz bu fonksiyonlarda bypass ediliyor

  8. Bartuc diyor ki:

    Bu fonksiyonları bypass eden bir method henüz bulunmadı. hastablog sisteminde(halka açık bir sistem) kullandığım için ve birçok yerde bu script kullanıldığı için, bypass edilseydi çoktan edilirdi fakat henüz böyle bir sorun yok.

  9. tamer diyor ki:

    id işlemleri sayısal saten is_numeric() fonksiyonu kullanmak yeterli.

    if(is_numeric($_GET['id']){
    devam
    } else {
    hata
    }

    kullanıcının sql ile direkten yani örnekte verdiğiniz gibi işlem yapcaksa her ihtimale karşı güvenlik betiği, zaman aşımı koyması daha sağlıklı olur.

    ellerine sağlık çok başarılı bir yazı olmuş.

Yorumunuzu Yazın