Uygulamalarımızda kullanıcı doğrulaması yada herhangi bir kontrol için SQL sorgusu gönderdiğimizde bu sorguyu gönderme biçimimize göre sistemimizde güvenlik açığı olabilir. Bu açıklık SQL-injection olarak adlandırılmaktadır. Bu açığı kullanarak
Örnek olarak bir kullanıcı giriş sistemini ele alalım, Genel olarak sistemlerin girişinde aşağıdaki gibi kullanıcıAdı ve Şifre istenmektedir.
Başlangıç seviyedeki yada SQL-injection ı bilmeyen kullanıcılar sisteme girişi kodlarken, genel mantık olarak
SQL deki kullanıcı adı ilk TextBox a eşitse VE SQL deki Şifre ikinci TextBox a eşitse
Select
*
from
tbKullanici
where
kAd=
'" + kAd + "'
AND
kSifre=
'" + kSifre + "'
Şeklinde bir sorgu gönderip bunun sonucunda dönen satır sayısı 0 dan büyükse sisteme gir şeklinde bir kodlama yaparlar. Böyle bir kodlama da kullanıcı TextBox lara ne değer girerse bu direk olarak SQL sorgusu olarak çalıştırılacağından kötü niyetli birisi burdan sisteminize sızarak veritabanınızda istediği herşeyi yapabilir desem heralde yanlış olmaz. Ne demek istediğimi daha iyi anlatmak adına örnek olarak aşağıdaki gibi bir giriş yapıldığını düşünelim
Text lere yukarıdaki gibi girdiğimizde SQL e giden sorgu şu şekilde olacaktır
Select
*
from
tbKullanici
where
kAd=
''
OR
1=1 /*
' AND kSifre='
*/
--'
Bunu daha derinden inceleyecek olursak
kAd=
''
OR
1=1
kısmına yazdığımız OR 1=1 ile kullanıcı adını bilmesek bile 1 herzaman 1 e eşit olacağından kullanıcı adını bilmeden girişi sağlamış olduk
/*
' AND kSifre='
*/
--'
kısmında ise şifre bölümü yoruma alınmış ve dewamı ise -- ile yorum olarak belirtilmiştir. Bu şekilde bir giriş ile parametresiz sisteme giriş yapabilir, tablo silebilir, istediğiniz değişikliği yapabilirsiniz
burada yapılacak şey saldıranın isteğine göre şekillenir. yukarıdaki gibi sisteme girmenin başka bir yolu ise aşağıdaki gibi olabilir, Sizde sorguyu istediğiniz gibi şekillendirerek farklı değerlerle giriş yapabilirsiniz
Yada sisteme zarar vermek isteyen birisi örneğin bir tablonuzu silebilir, kaldırabilir, yeni tablo ekleyebilir, veri girişi yapabilir... tabi bu işlemler için tablo ismini de bilmesi gerekir ama sisteme basit bir kullanıcı hesabıyla dahi girmiş olsa bile sql sorgusu ile bütün tablo isimlerini öğrenmek de mümkün. Şimdi basit bir örnekle örneğin sistemimizde tbFaruk isminde bir tablo olduğunu düşünelim. Saldıran kişi bu tabloyu silmek isterse aşağıdaki gibi bir metin girerek bunu başarabilir
Select
*
from
tbKullanici
where
kAd=
''
OR
1=1;
DROP
TABLE
tbFaruk /*
' AND kSifre='
*/
--'
Böyle bir giriş ile tbFaruk tablosu kaldırılmış olur. Saldıracak kişi burdaki ; den sonra istediği SQL Script ini yazarak veritabanınızı değiştirebilir
Kodlarken SQl injection tehlikesi altında olan örnek kodlama aşağıdaki gibi bir yapıdadır
string
kAd = txtKullaniciAdi.Text;
string
kSifre = txtSifre.Text;
DataTable tbl =
new
DataTable();
string
sql =
"Select * from tbKullanici where kAd='"
+ kAd +
"' AND kSifre='"
+ kSifre +
"'"
;
SqlDataAdapter adap =
new
SqlDataAdapter(sql, conn);
adap.Fill(tbl);
if
(tbl.Rows.Count > 0)
{
//yapılacak işlem
// diğer sayfaya geçiş vs...
MessageBox.Show(
"!!!Sisteme Girildi!!!"
);
}
Bunun yerine parametre göndermeli bir yapı tercih etmemiz gerekir. Böylece SQL-injection dan kaynaklı güvenlik açığını da ortadan kaldırmış oluruz. Buna örnek güvenli bir kod yapısı ise aşağıda belirtilmiştir
conn.Open();
string
sql =
"Select * from tbKullanici where kAd=@parametre1 AND kSifre=@parametre2"
;
SqlCommand command =
new
SqlCommand(sql,conn);
command.Parameters.AddWithValue(
"@parametre1"
, txtKullaniciAdi.Text);
command.Parameters.AddWithValue(
"@parametre2"
, txtSifre.Text);
SqlDataReader dr =command.ExecuteReader();
// isterseniz de datatable a aktararak kullanabilirsiniz
DataTable tbl =
new
DataTable();
tbl.Load(dr);
if
(tbl.Rows.Count > 0)
{
//yapılacak işlem
// diğer sayfaya geçiş vs...
MessageBox.Show(
"!!!Sisteme Girildi!!!"
);
}
conn.Close();
Bu şekilde parametreli bir yapı kullanarak saldırıların ve yetkisiz işlem yapmak isteyenlerin önüne geçmiş, onları engellemiş olursunuz. Parametreli güvenli sistemi kullandığınızda yukarıdaki saldırı text lerini girseler dahi sistem bunu kabul etmeyecektir
Sistemlere giriş illaki TextBox lar ile değil session ile, queryString ile vs... de yapılabilir. Eğer buralardaki metni direk yukarıdaki güvensiz yöntem ile sql sorgusuna yazarsanız yine aynı şekilde sql injection ile karşılaşacaksınız ve sisteminizde güvenlik açığı olacaktır
Yada başka bir örnek inceleyecek olursak mesela kitap numarası yada öğrenci numarası girildiğinde bir tabloya ilgili kişinin yada kitabın bilgilerini döken bir uygulama modülümüz olduğunu düşünelim
string
sql =
"Select * from tbKisi where kisiNo="
+ txtKisiNo.Text;
Kullanıcının sadece bir kişi yada sadece bildiği kişi numaralarını görebileceği bir sistemde (yukarıdaki sistem basit anlamda olayı anlatmak için tasarlanmıştır, buraya bir GUID vs gibi yapı ile daha güvenli bir sistem de planlanabilir ama burda asıl konumuz SQL injection olduğundan basit bir örnek ele alınmıştır) kullanıcı KişiNo yerine aşağıdaki gibi bir text girdiğinde bütün sistem kayıtları dökülecektir
Select
*
from
tbKisi
where
kisiNo=127
OR
1=1