SQL Injection - UNION ile Data Okuma
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
Yorum Ekle
SQL Injection - UNION ile Data Okuma ile İlişkili Olabilecek Yazılar - Haberler
BSQL Hacker and Deep Blind SQL InjectionsBSQL Hacker Videosu
RIATalks' un Ardından
RIATalks' ta Buluşalım
My Love is Killing Me
Diğer Yazılar
SQL Injection Cheat Sheet
SQL Injection Cheat Sheet is Online !
SQL Injection Cheat Sheet Online!
SQL Injection Cheat Sheet Yenilendi
SQL Injection' dan Korunma Videosu
SQL Injection' dan Korunma Videosu
SQL Injection Dersleri
SQL Injection Dersleri - Union ile Data Okuma
SQL Injection Dersleri Başladı
Neredeyim ?
Ferruh.Mavituna » SQL Injection Dersleri » SQL Injection - UNION ile Data Okuma