SQL Injection - UNION ile Data Okuma

01.03.2007

Okuyucu : 8.159
Günlük Okuyucu : 15,1

SQL Injection - UNION ile Data Okuma

SQL Injection’ ın sadece üye giriş ekranları için geçerli olduğunu sanıyorsanız bir çok web programcısı gibi çok zararlı bir fikre sahipsiniz demektir. SQL Injection bir çok yerde bir çok şekilde olabilir.

SQL Injection açıkları eğer üye giriş ekranında değilse en faydalı şey SQL Injection ile veritabanındaki istediğiniz tablodan data okumaktır. “Üyeler” veya “Siparişler” tablosu gibi. Örnek olarak bir ürün detay sayfasındaki SQL Injection ile tüm üyelerin şifrelerini alabilirsiniz.

SQL Injection’ da data okumak için birden fazla yöntem bulunmaktadır ancak UNION komutunu kullanarak dataları almak genelde en çok kullanılan ve en pratik yöntemdir.

Union Nedir?

Union kelimesi SQL cümleciğinde iki tablodan birden kayıt çekmek için kullanılır. Örnek datalarla Union un nasıl çalıştığına bir bakalım.
İki tablomuz var biri “products” diğeri ise “brands”.

Örnek datalar aşağıdaki gibi;

products (productname field) – 4 kayıt

     -	Pencil
     -	Swedish Design bed
     -	Computer Desk
   -	Deckan Chair
brands (brandname  field) – 2 kayıt
     -	Cool Pens
     -	Dream Store Designers

    

> SELECT productname FROM products;
> GO;

Pencil
Swedish Design bed
Computer Desk
Deckan Chair

4 records

 

Basit bir SQL ile products tablosundaki tüm kayıtları getirdik.

> SELECT brandname FROM brands;
> GO;

Cool Guys
Dream Store Designers

2 records

Gene aynı şekilde brands tablosundaki tüm kayıtları getirdik. Şimdi Union ile iki tablodan birlikte kayıtları getirelim.

> SELECT productname FROM products UNION SELECT brandname FROM brands;
> GO;

Computer Desk
Cool Guys
Deckan Chair
Dream Store Designers
Pencil
Swedish Design bed

6 records

Yeni SQL cümleciği iki tablodaki kayıtları da birleştirip toplam 6 kayıt getirdi.  SQL Injection ataklarında biz de benzer şekilde başka tablolardaki kayıtları mevcut kayıtlar ile birleştirip ekrana yazdırabiliriz.

SQL Injection Açığı Bulunan Örnek Bir Sayfa

Aşağıda SQL Injection açığı bulunan örnek bir ASP sayfasının kodu var. Bu sayfa arama sayfası üzerinden SQL Injection ile üyeler tablosundaki kayıtları çekip şifreleri alacağız.

Arama Sayfası ASP Kodu;

<%
1.    Dim RsProducts, SQL, QSearch, Desc
2.    QSearch = Request.Querystring("q")
3.   
4.    Set RsProducts = SQLConn.Execute( "SELECT product_id, name, description, price, stock FROM Products WHERE name LIKE '%" & QSearch & "%' " )
%>

ASP sayfası 2. satırda Request.Querystring("q") kodu ile ziyaretçinin arama kutusuna girdiği değeri alıyor ve QSearch değişkeninde tutuyor.

4. satırda ise arama sonuçlarını getirecek SQL cümleciği çalıştırılıyor. Görüldüğü gibi burada Qsearch parametresi filtre edilmeden direk veritabanına gönderiliyor.

Önce SQL Injection açığını denemek için basit şekilde bir (‘) tırnak işareti kullanıyoruz ve aşağıdaki ekran ile karşılaşıyoruz ki bu da sayfada SQL Injection olduğunu tam anlamı ile onaylıyor.

Microsoft OLE DB Provider for SQL Server (0x80040E14)
Unclosed quotation mark after the character string ' '.
/SQLInjection/Productsearch/Default.asp, line 14

Şimdi bu masum SQL cümleciğini kendi kötü emellerimize alet edelim ve arama kelimesini deneyelim. Buradaki arama formu GET metodu kullandığına göre kolayca “q” parametresini URL üzerinden düzenleyebilir ve yeni bir istekte bulunabiliriz.

Buradaki örnekte veritabanı yapısını (tablo isimleri, alan isimleri vs.) bildiğimizi varsayıyoruz. İleriki bölümlerde veritabanı yapısının nasıl bulunabileceğine değineceğiz.

Enjekte edeceğimiz SQL cümleciği;
aaa' UNION ALL SELECT 1,username,password,1,1 FROM Members --

Demek ki istek yapacağımız sayfa şu şekilde olmalı;
/default.asp?q= aaa' UNION ALL SELECT 1,username,password,1,1 FROM Members --

Bir de şimdiki sonuçları inceleyelim;

Gördüğünüz gibi arama sonuçlarında ürünler yerine üyelerin şifreleri ile birlikte bir listesi var.

Atağı İnceleyelim;

Şimdi yukarıdaki atağı nasıl hazırlandığını inceleyelim.

aaa' UNION ALL SELECT 1,username,password,1,1 FROM Members --

Burada sadece UNION yerine UNION ALL kullanıyoruz çünkü UNION kullanırsak sistem iki tablodaki datalardan sadece tekil olanları getirmeye çalışacak. Yani iki tarafta da olan dataları sadece bir defa göreceğiz. Dataları almaya çalışırken olası sorunlardan kendimizi korumak her zaman UNION ALL kullanmak daha iyi bir seçimdir.

Öncelikle kendi SQL komutlarımızı enjekte etmek için string’ ten çıkmamız lazım. Bunun için aaa’gibi bir şey ile başlayarak () tırnak işareti sayesinde veritabanının bundan sonra gelen kelimeleri SQL komutu olarak algılamasını sağlıyoruz. Bu işlemi hemen hemen her türlü SQL Injection da uygulamamız gerekiyor.

UNION injectionlarında birinci kural ikinci SQL cümleciği ile birinci SQL cümleciğinin aynı sayıda alan (field) kullanması gerektiğidir (yani select cümleciklerinde aynı sayıda alan çekmesi) aksi takdirde aşağıdaki gibi bir hata ile karşılaşırız.

Microsoft OLE DB Provider for SQL Server (0x80040E14)
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
/SQLInjection/Productsearch/Default.asp, line 15

Dolayısıyla bu hatayı almamak ve başarılı şekilde SQL injection yapabilmek için enjekte ettiğimiz SQL cümlesinde de aynı sayıda alan çekiyoruz. Yukarıdaki atakta biz soldaki SQL cümleciğini (SELECT product_id, name, description, price, stock FROM Products)  bildiğimizden sağdaki kısma da beş adet alan girmemiz gerektiğini biliyoruz.

Black-Box Union SQL Injection
Bir sonraki bölümde bu tablo yapısı, SQL cümleciğini bilmeden tamamen bilmediğimiz bir sistemde nasıl UNION SQL Injection yapılacağını göstereceğiz.

UNION injection’ ların ikinci önemli kuralı ise iki taraftaki alanların sırası ile birleştirildikleri alan ile aynı tipte olmalı gerekiyor. Örnek olarak soldaki ilk alan integer ise sağdaki ilk alan da integer olmalıdır.

Union Injection’ da Data Tipleri
Tüm veritabanları genelde 4 ana tip kullanılar. Integer, String, Date ve Binary bunun haricindeki alt birimler genelde birbirlerine sorunsuz olarak otomatik şekilde veritabanları tarafından otomatik olarak cast edilirler. Örnek olarak float bir alana rahatça 3 yazabilir ya da memo bir alana basit bir şekilde ‘test’ metnini girebiliriz.

Demek ki enjekte edeceğimiz SQL cümleciği şu yapıya sahip olmalı;

SELECT integer, string, string, integer, integer

Biz Members tablosundaki kayıtları çekmek istediğimize göre ve bu tablodan sadece username ve password alanlarına ihtiyaç duyduğumuza göre şu şekilde bir SQL cümleciği hazırlayabiliriz;

SELECT 1, username, password, 1, 1 FROM Members

Dikkat ederseniz username ve password alanlarını string olan alanlarla aynı sıraya koyduk diğer alanlara ise 1 koyduk. Burada 1 koymamızın özel bir nedeni yok sadece orada bir integer bir değer bulunması gerektiğinden herhangi bir rakam koyduk. 166, 917 veya herhangi başka bir rakam da koyabilirdik.

Son olarak daha önceden de gördüğümüz “--“ iki tire ile SQL cümleciğinin geri kalan kısmının çalışmamasını ve yorum olarak algılanmasını sağlıyoruz.

Ve en sonunda atağımızı oluşturuyoruz,

' UNION ALL SELECT 1,username,password,1,1 FROM Members --

Oluşturduğumuz bu cümleciği direk arama kutusuna girebilir ve ara butonuna basabilir ya da URL üzerinden gönderebiliriz.

Herşey çok güzel, gördüğünüz gibi kullanıcı adları ve şifreler de arama sonuçlarında gözüküyor. Eğer biraz daha güzel bir sonuç istersek arama kelimesine veritabanında bulunmayan bir şeyler girebilir ve bu sayede sadece members tablosundaki dataların gözükmesini sağlayabiliriz.

Union Injectionlarda Sadece İstenilen Tabloyu Getirme
Bu tip saldırılarda sadece sağdaki cümleciğin sonuçlarını getirmek tek sayfada sınırlı sayıda kayıt (bazen sadece bir!) getiren uygulamalarda çok kritik bir rol oynayabilir.

Bunun için soldaki cümlenin kayıt getirmemesini sağlamamız gerekiyor. Eğer soldaki cümle bir arama yapıyorsa çıkmayacak bir arama kelimesi girebiliriz, eğer bir nümerik değer bekliyor ve bunu kullanıyorsa -1 gibi bir değer verip kesinlikle sonuç gelmemesini sağlayabiliriz.

Bu son değişikliği de yaptığımız son saldırı cümleciğimiz şu şekilde oluyor;

aaa' UNION ALL SELECT 1,username,password,1,1 FROM Members --

Arka planda veritabanında çalışan SQL cümleciği ise şu şekilde;

SELECT product_id, name, description, price, stock FROM Products WHERE name LIKE '%aaa' UNION ALL SELECT 1,username,password,1,1 FROM Members –-%'

Yukarıda kırmızı kısım bizim dışarıdan eklediğimiz SQL cümleciği (yani enjeksiyonumuz) , yeşil kısım ise “--“  den dolayı SQL Server tarafından iptal edilip çalıştırılmayan bölge. Eğer çalışsaydı SQL cümleciğinin sentaksı yanlış olacağından hata alacaktık. Bu yüzden en basit şekilde bizim işimizin bittiği yerden sonrasını iptal ettik. Sonuç olarak kendi SQL cümleciğimizi başarılı şekilde enjekte ettik ve sonuçların içerisine members tablosundan kayıtları da eklettirdik. Artık bu kullanıcılar ile siteye üye girişi yapabiliriz!

 

Yorumlar

RSS Bu makalenin yorumlarını RSS ile takip et!

gerçekten çok açiklayici bir döküman olmus Ferruh Bey,en yakinda bu tür açiklarin fixlenmesiyle ilgili bir tuttorial bekliyoruz.(umarim herkes bekliyordur :) )

Kerem Inanc [ # | 02.03.2007 ]

Merhabalar,

-- ya da /* seklinde SQL komutunu kesmek access veritabaninda ise yaramiyor mu ?

Bir de access veritabaninda UNION ile data okumayi bir türlü basaramadim. Microsoft Access programinin sorgu sayfasinda yazdigim UNION ile data okuma sorgusu basariyla çalisiyorken ASP dosyasinin içine aynen yazdigim SQL sorgusu "Çok az parametre. 1 fazla bekleniyor." Gibi bir hatayla sonuçlaniyor.

Simdiden tesekkürler. SQL makalelerinin devamini bekliyoruz..

Fatih Birkan [ # | 03.03.2007 ]

Güzel bi çalisma daha, tesekkür ederiz.

Escape karakterleri fixlemek temel bi fix olabilir.

Gehinnom [ # | 04.03.2007 ]

Derslerinizi ilgiyle takip ediyorum sayin Ferruh Mavituna. Umarim bilgileriniz kötü niyetli kisilerin eline alet olmaz. Yazi diziniz için tesekkürler.

Cemil Durgan [ # | 30.06.2007 ]

Database'deki ilk kaydi getirme .
YANI kullanici adi ve sifreyi geri getirebilmek için en basit kod nedir ve nasil yazilmaliidir bu açiklamayi çok kisinin bekledigini biliyorum

hack_jaws [ # | 20.02.2008 ]

Yorum Ekle





Kullanılabilir Taglar : [<blockquote>] [<strong>] [<em>]

SQL Injection - UNION ile Data Okuma ile İlişkili Olabilecek Yazılar - Haberler

BSQL Hacker and Deep Blind SQL Injections
BSQL Hacker Videosu
RIATalks' un Ardından
RIATalks' ta Buluşalım
My Love is Killing Me

Diğer Yazılar

Neredeyim ?

Ferruh.Mavituna » SQL Injection Dersleri » SQL Injection - UNION ile Data Okuma

Ferruh Mavituna
© 2002-2007, Ferruh Mavituna

Sabit IP Adresi : 81.22.99.133, SSL Erişimi, Hakkında