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.
1. <%
2. Function security(data)
3. data = Replace (data ,"`" ,"" ,1,-1,1)
4. data = Replace (data ,"=" ,"" ,1,-1,1)
5. data = Replace (data ,"&" ,"" ,1,-1,1)
6. data = Replace (data ,"%" ,"" ,1,-1,1)
7. data = Replace (data ,"!" ,"" ,1,-1,1)
8. data = Replace (data ,"#" ,"" ,1,-1,1)
9. data = Replace (data ,"<" ,"" ,1,-1,1)
10. data = Replace (data ,">" ,"" ,1,-1,1)
11. data = Replace (data ,"*" ,"" ,1,-1,1)
12. data = Replace (data ,"/" ,"" ,1,-1,1)
13. data = Replace (data ,"\" ,"" ,1,-1,1)
14. data = Replace (data ,"And" ,"" ,1,-1,1)
15. data = Replace (data ,"'" ,"" ,1,-1,1)
16. data = Replace (data ,"Chr(34)" ,"" ,1,-1,1)
17. data = Replace (data ,"Chr(39)" ,"" ,1,-1,1)
18. security=data
19. End Function
20. %>
'Yukarıdaki function'ı aşağıdaki şekilde sayfaya eklemenizin ardından kullanabilirsiniz.
1. <%
2. sUserId = security(Request.Form("userid" ))
3. sPassWd = security(Request.Form("passwd" ))
4. %>
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. |