Dünyanın her tarafında, kullanıcılarına, kredi
kartı numaraları, kullanıcı bilgileri gibi gizli kalması gereken bilgilerin,
ürünlere ve siparişlere ait verilerin saklandığı uç-arka veri depolarıyla
hizmet veren web siteleri bulunmaktadır. Ve genel olarak, web sitelerindeki
form aracılığı ile alınan girdi ile veritabanındaki bilgiler filtrelendikten
sonra sonucu kullanıcıya gönderen bu tür sistemlerde Yapısal Sorgulama Dili
(Structured Query Language - SQL) kullanılmaktadır. Uygulama içerisinde
kullanılacak parametre değerleri alınırken kullanılan formun SQL deyimini
yeniden yapılandırabilecek bazı özel karakterlere izin vermesiyle güvenlik
problemleri ortaya çıkmaktadır.
Bu güvenlik problemleri kullanılarak bir uygulamanın arkasında bu uygulamaya
destek veren veri tabanı üzerindeki bütün bilgilere ulaşılabilir veya bilgiler
üzerinde değişiklik yapılabilir. Veya veri tabanı sisteminin komutları
kullanılarak kullanılan sunucular üzerinde uygulama harici istenen işlemler de
yapılabilir. Bu problemlerden korunmak için de uygulama girdilerini bu tür
karakterlere karşı kontrol eden
fonksiyonlar kullanılmalı ve geniş çaplı uygulamaların bu güvenlik açıklarını
taşıyıp taşımadığını anlamak için güvenlik denetimine tabi tutulmalıdır.
İşte bu Microsoft ürünü
veritabanı programlama dili günümüzde en çok tercih edilen yapısal dilidir.
Microsoft'un ASP teknolojisine uyarlayıp donattığı SQL, bazı art niyetli
insanlar tarafından kötü işler için kullanılmakta. Hackerlar SQL sorgulamasını
yanıltıp kendi verdiği parametrelerle bu yapıyı hataya zorluyor. Şimdi bu
hataları ayrıntılarıyla inceleyelim.
SQL
Saldırıları (SQL Injection)
Web uygulaması geliştiricileri SQL injectionı
tam anlamadıklarından dolayı bazı ölümcül hatalar yaparlar. Bu yüzden bugün
bilinen basit SQL injection metodları o kadar çok görünmese de bu yöntemi iyi kavrayan biri için
siteden istediği bilgileri çekmek çocuk oyuncağıdır.
Web uygulamalarında birçok işlem için
kullanıcıdan alınan veri ile dinamik SQL cümlecikleri oluşturulur. Mesela “SELECT
* FROM Products” örnek SQL cümleciği basit şekilde veritabanından web
uygulamasına tüm ürünleri döndürecektir. Bu SQL cümlecikleri oluşturulurken
araya sıkıştırılan herhangi bir meta-karakter SQL
injectiona neden olabilir.
Şimdi hangi sitelerde SQL açığı var bunu nasıl
öğrenebiliriz onu inceleyelim. SQL injectionda hatalar çok önemlidir. Başlarken, siteye
saçma bir SQL sorgusu göndereceğiz o da haliyle bize bir hata mesajı verecek. Biz
bu hata mesajını inceleyip içinden bazı ipuçları bulmaya çalışacağız. Mesela,
bir sitede kullanıcı girişi yapılan bölüme kullanıcı adı ve şifre bölümüne ’ or
1=1-- yazalım enter diyelim. Sitede SQL açığı varsa şöyle bir hata vermesi
lazım :
Microsoft OLE DB Provider for ODBC Drivers
error ’80040e07’
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the
nvarchar value ’users’ to a column of data type int.
/index.asp, line 11
İşte böyle bir hata aldık.
Bu hatayı Türkçeleştirirsek eğer;
Microsoft
Veritabanı Sürücü hatası ’80040e07’
SQL
Server 'users' tablosunda eşleştirme yapmak için geçerli bir değer
girmediniz, söz dizimi
hatası oluştu.
/index.asp,
satır 11
SQL’de sorgular bitmez.
’
or 1=1--
" or 1=1--
’ or ’a’=’a
or 1=1--
’) or (’a’=’a
" or "a"="a gibi parametreler de
kullanılabilir.
Yukarıda
kullanıcı adı ve şifre bölümüne ’ or 1=1-- yazmamızın sebebi giriş
şartı hiçbir şey olsun veya 1=1 durumları olsun.(1 her zaman 1 e eşit
olduğundan her
zaman
bu komut çalışır.)
Başka
bir yöntem:
Mesela; sitede “babalar” adlı bir
tablo var bu tabloda “ogullar”
adında bir iç tablo var.
Biz burada “babalar”
tablosunun “ogullar”
tablosundaki bütün kayıtları seçmek için SQL’de şöyle bir komut kullanırız.
SELECT * FROM babalar
WHERE urunID=’ogullar’
Biz babalar
adlı tablodan haberdar olmadığımız için şöyle bir komut girersek
SELECT * FROM ogullar
WHERE urunID=’’ or 1=1--’
yani “ogullar”ın
içinden “urunID”si boş olan veya “urunID”si 1=1 eşitliğini sağlayan tabloyu
getir diyoruz.
Her şartta 1=1 olduğundan SQL mantıksal eşlenimi yapamadığından dolayı hata verdi ve hiç bilmediğimiz
kolon adlarını getirecek. Şimdi daha fazla ilerlemeden SQL injection neden
oluşur bir göz atalım.
SQL
injection, web sitelerine kurulan database yani veri tabanının içerdiği
sayfaların, sitenin webmasterı tarafından görünümü güzelleştirmek, çekiciliği
artırmak, kullanıcı adlarını yanlış filtrelemek gibi nedenlerle çeşitli
kodlarla oynaması, dikkatsizce yazılmış kod sayfaları veya sitenin geçmişini
kaydetmek gibi bilimum nedenlerden dolayı oluşur. Login
sayfaları, destek veya ürün istek formlar, yorum/iletişim formları, arama
sayfaları, alışveriş sepeti sayfaları dinamik içeriğin sunulduğu çeşitli
sayfalardır ve modern iş dünyasında müşteriler ile veya kullanıcılar ile
haberleşmede vazgeçilmezdir.
Bir SQL injection saldırısı örneği
Login ve şifreden oluşan iki giriş kabul eden basit bir HTML
formunu inceleyelim:
< form method="post" action="http://bilisimdunyasi/login.asp">
< input name="tfUName" type="text"
id="tfUName">
< input name="tfUPass" type="password"
id="tfUPass">
< /form>
login.asp'nin en kolay çalışma şekli aşağıdaki
gibi bir veritabanı sorgusu hazırlamakla olabilir:
SELECT id
FROM logins
WHERE username = '$username'
AND password = '$password’
Eğer
$username ve $password değişkenleri kullanıcı girişinden direkt olarak alınıp SQL
sorgusunda kullanılıyorsa çok kolay bir şekilde hack edilebilir demektir.
Kullanıcı adı olarak "Olympos" verdiğimizi ve şifre için de
aşağıdakini yazdığımızı varsayalım:
falan' OR 'x'='x
SELECT id
FROM logins
WHERE username = 'Cemre'
AND password = 'falan' OR 'x'='x'
Web uygulamasında kullanıcı girişleri doğru
olarak filtrelenmediği için, tek tırnak kullanımı WHERE SQL komutunu iki bileşenli
bir sorguya dönüştürdü.
'x'='x' bölümü ilk bölüm ne olursa olsun şartın
doğru olmasını garantiler. Bu işlemle de saldırganın amacı veri tabanını mantıksal hataya zorlamak
ve x her zaman x e eşit olduğundan sistemin afallamasını sağlamaktır.
Bu da saldırganın login formunu geçerli bir
kullanıcı / şifre kombinasyonu bilmesine gerek kalmadan aşabilmesini sağlar. SQL saldırılarının zarar boyutu, komutları
bilme ve kullanabilme kabiliyetine göre artar ya da azalır. Bir sitede SQL
açığı var mı, injection yapılabilir mi şöyle anlaşılır: www.falancasite.com/news.asp?id=38
sitemiz bu olsun şimdi biz site url’sini www.falancasite.com/news.asp?id=38'a
şekline getirirsek alacağımız hataya göre saldırı çeşitlenebilir.
Bahsettiğimiz gibi SQL injection, Access, MySQL, MSSQL oluşuna göre değişik
yöntemler içeren saldırı türüdür. Güvenlik açısından daha fazla detaya girmeden
MySQL injection komutalarına göz atalım:
MySQL
injection komutları
information_schema.columns - tables: Tüm
columns ve tableları listeler.
table_schema -
table_name - column_name: Sistem tablolarımız.
Limit+192,1:
192. Sayfada 1 kaydı gösterir.
concat(table_schema,0x3a,table_name,0x3a,column_name):
Tablo komutu.
Eğer
SQL açıklı site aramak isterseniz
news.asp?id=
news_detail.asp?id=
product.asp?id= gibi kodları Google'da aratarak deneyebilirsiniz.
Sql
Korunma Yöntemleri
SQL injectiondan korunmada iki altın kural
vardır.
Tüm
meta-karakterlerden kaçınılmalıdır yani /,-- gibi karakterlere izin verilmemelidir
Nümerik
olarak beklenen parameterlerin nümerik olup olmadığı kontrol edilmelidir.
- <%
- Function security(data)
- data = Replace (data ,"`"
,"" ,1,-1,1)
- data = Replace (data ,"="
,"" ,1,-1,1)
- data = Replace (data ,"&"
,"" ,1,-1,1)
- data = Replace (data ,"%"
,"" ,1,-1,1)
- data = Replace (data ,"!"
,"" ,1,-1,1)
- data = Replace (data ,"#"
,"" ,1,-1,1)
- data = Replace (data ,"<"
,"" ,1,-1,1)
- data = Replace (data ,">"
,"" ,1,-1,1)
- data = Replace (data ,"*"
,"" ,1,-1,1)
- data = Replace (data ,"/"
,"" ,1,-1,1)
- data = Replace (data ,"\"
,"" ,1,-1,1)
- data = Replace (data ,"And"
,"" ,1,-1,1)
- data = Replace (data ,"'"
,"" ,1,-1,1)
- data = Replace (data ,"Chr(34)"
,"" ,1,-1,1)
- data = Replace (data ,"Chr(39)"
,"" ,1,-1,1)
- security=data
- End Function
- %>
'Yukarıdaki function'ı aşağıdaki şekilde
sayfaya eklemenizin ardından kullanabilirsiniz.
- <%
- sUserId =
security(Request.Form("userid" ))
- sPassWd =
security(Request.Form("passwd" ))
- %>
|
PHP için injectiondan korunmanın en basit
yöntemi ise şöyledir:
$_POST veya $_GET ile gelen bütün değerleri ENT_QUOTES parametresi kullanılan
htmlspecialchars fonksiyonundan geçirin.
Örnek:
$_POST['sifre'] yerine
htmlspecialchars($_POST['sifre'], ENT_QUOTES
Ve
ayrıca bir ASP sitesinde de güvenliği artırmak için;
Sayfalarda tanımlayıcı hata
mesajları kullanmamak: Kullanıcılara hata mesajları
gösterilirken daha genel açıklamalar verilmeli. Örneğin bir login sayfasında
kullanıcı hata mesajından faydalanarak kullanıcı adı veya şifre bilgisini
tahmin etmemeli.
“Kullanıcı adı hatalı”
“Şifre hatalı”
“Şifre 6 karakterden uzun olmalı”
gibi hata mesajları yerine
“Kullanıcı adı veya şifre hatalı. Lütfen
bilgilerinizi kontrol ediniz” denilebilir.
Kullanıcıların upload ettikleri
dosyaların uzantısını kontrol etmek: Uygulamada
upload kontrolü var ise sadece istediğimiz türdeki dosyaların yüklenmesine izin
verilmeli. Çünkü yüklenen dosyalar webden erişilebilen bir
klasörün altına kaydedilir ve yükleyen kişi browserdan yüklediği dosyayı
çağırarak serverda dosyayı çalıştırabilir.
Kara listedeki dosyalar: asp, aspx, php. Gözardı edilmemelidir.