SQL Injection Nedir ve Nasıl Korunulur?

Cryptograph 16.10.201218:22 Bilgi Güvenliği 8005    
Facebookta Paylaş

SQL Injection web uygulamalarında ki en ciddi açıklardan biridir. Özellikle frameworklerin popülerleşmesi ile eskisine göre bugünlerde biraz daha az görülmektedir ama emin olun hala bir çok sitede var bu açıklar!


Web uygulama geliştiricileri SQL injectionu tam anlamadıklarından bu tarz hatalar yaparlar.


SQL injection veritabanından ve dilden bağımsız olarak her türlü veritabanı ilişkisi bulunan uygulamada bulunabilirler ve bu veritabanı açığı değildir.

SQL Nedir?

SQL (Structed Query Language) veritabanından bilgi çekme, bilgi ekleme, bilgi silme ve bilgi güncelleme işlemlerinin yapılması için kullanılan bir dildir, hemen hemen her uygulamada (web uygulaması, masaüstü uygulamaları) veritabanı desteği vardır.


Örnek olarak ben bu siteye konu eklediğim zaman bu konu veritabanına ekleniyor daha sonra site içerisinde veritabanından gelerek siz ziyaretçiler bu konuları okuyorsunuz, yorum yaptığınızda kaydediliyor ben onayladığımda güncelleme işlemi yapıyor ve yorum yayınlanıyor.

Örnek bir silme komutu: DELETE FROM blog WHERE id=1 blog tablosundaki id değeri 1 olan kaydı silecektir.

Bu konuyu sqlin temel komutlarını ve mantığını anlamış olduğunuzu varsayarak anlatıyorum.

 

 SQL Injection Nedir?

Web uygulamalarında bir çok işlem için kullanıcıdan alınan veri ile dinamik SQL sorguları oluşturulur. Mesela ?SELECT * FROM blog WHERE id=1? örnek SQL sorgusu basit şekilde veritabanından web sayfasına id değeri 1 olan blog konusunu getirecektir. Bu SQL sorguları oluşturulurken araya karıştırılan herhangi bir meta-karakter SQL Injection? a neden olabilir.


Meta-Karakter

Meta-karakter bir yazılım için özel anlamı olan karakterlerdir. Derleyici ya da yorumlayıcı bu karakteri görünce ondan sonraki karakteri ona göre işler. SQL için en kritik meta karakter (') tek tırnaktır, çünkü iki tırnağın arası string olarak algılanır ve diğer meta karakter ise (;) noktalı virgül karakteri, bu karakter komutun bittiği ve yeni komutun bağlayacağını belirtir.

SELECT * FROM profil WHERE kullanici_adi='admin' AND sifre='12345'
formdan gelen kullanıcı adı ve şifre bilgisiyle bu sql sorgusu oluşturuldu, eğer kullanıcı adı ve şifre doğruysa oturum açılır, değilse yanlış kullanıcı adı veya şifre uyarısı verebilir. Buraya kadar herşey normal, ama kullanıcı giriş panelinden meta karakter gönderilirse siteye admin yetkileriyle giriş yapılabilir.


PHP`de örnek bir giriş paneli sistemi:

<?php
$kullanici_adi = $_POST['kullanici_adi'];
$sifre = md5($_POST['sifre']);
if(mysql_query('SELECT * FROM profil WHERE kullanici_adi="'.$kullanici_adi.'" AND sifre="'.$sifre.'"')){
 echo 'Giriş başarılı.';
}
else echo 'Giriş başarısız.';
?>
Gayet sorunsuz görünüyor fakat öyle değil, kullanıcı panelinden gönderilecek bir (') tek tırnak işareti komutu sonlandırır, yada komutu şöyle düzenleyebilir
SELECT * FROM kullanicilar WHERE kullanici_adi='OR sifre=  OR' )
yani kullanıcı adı ve şifre yerinden OR yazdığımızda başarılı bir şekilde giriş yapabiliriz, bu şekilde sorgu çalıştırıldığında boş = boş olur ve tüm kullanıcıları getirir, doğal olarak en başta admin yetkilerine sahip kullanıcı geleceği için siteye admin yetkileriyle giriş yapmış oluruz.

Daha farklı bir yöntemse şudur; bazı sitelerde görürüz adres satırında .php?id=75 gibi değerler olur, buradaki sorgu ise şudur
SELECT * FROM konular WHERE id=75
Adres satırından get methodu ile gönderilen id değeri sayfada çalıştırılacak olan sql sorgusunda yerine yazılır ve ona göre konu ekrana getirilir.

Örnek sorgu:
<?php
$id = $_GET['id'];
$konusorgu = mysql_query('SELECT * FROM konular WHERE id='.$id);
?>
Burada ise blog.php?id=75 yerine farklı bir id değeri gönderebiliriz, 75 yerine bir tırnak attığımızda site hata verecektir ve buradan sql sorgusu çalıştırmaya ve web sayfasının rahat bir şekilde manipule edilmesini sağlayacaktır. Bunlardan korunmak için GET veya POST ile aldığımız verileri filtreden gerçirmemiz gerekli.

blog.php de gönderilecek olan değerin integer tipli olup olmadığını kontrol ederekte bundan bir nevi korunmuş oluruz ama yinede gerekli filtrelerden geçirmemiz gerekli
is_numeric() : Bu fonksiyon değerin numara olup olmadığını kontrol eder.
strip_tags() : Bu fonksiyon html etiketleri temizler.
htmlspecialchars() : Bu fonksiyonda html etiketlerini temizler.
addslashes() : Bu fonksiyon post veya get ile gönderilen ' tek tırnak veya " çift tırnak karakterlerinin başına /karakteri ekler ve program tarafından string olarak algılanmasını sağlar.
mysql_real_escape_string() : Mysql de kullanmak için stringleri uygun biçime dönüştürür.


Şimdi bu sorguların doğru kullanımlarını görelim

PHP`de DOĞRU bir giriş paneli sistemi:

<?php
$kullanici_adi = addslashes(mysql_real_escape_string(strip_tags(htmlspecialchars($_POST['kullanici_adi']))));
$sifre = md5(addslashes(mysql_real_escape_string(strip_tags(htmlspecialchars($_POST['sifre'])))));
if(mysql_query('SELECT * FROM profil WHERE kullanici_adi="'.$kullanici_adi.'" AND sifre="'.$sifre.'"')){
 echo 'Giriş başarılı.';
}
else echo 'Giriş başarısız.';
?>


Blog veya konular için olan blog.php DOĞRU kod sistemi:
<?php
$id = addslashes(mysql_real_escape_string(strip_tags(htmlspecialchars($_GET['id']))));
if(!is_numeric($id){
 echo 'Yanlış istekte bulundunuz';
 exit;
}
$konusorgu = mysql_query('SELECT * FROM konular WHERE id='.$id);
?>

Okuyucu Yorumları (0 Yorum)

Söz Sırası Sizde

Benzer Konular

Benzer KonularPaylaşmanın asaletini hiçbir zaman bencilliğin çirkinliğine bırakmayın!

​​​​​​​​​​​​​​​​​​​​​​​​​

MERAK EDİLENLER

İLETİŞİM

  • alpay[at]cryptograph.gen.tr
  • İstanbul ikametgah