Anlamak Gerek
Sql injection için ilk aşama hata verdirmekti ya da mantıksal sorgulara cevap verip vermediğini test etmekti bunları ilk yazımızda anlatmıştık. Her şeyin başı anlamak. SQL Injection hatasını ezbere almamak gerek kullandığımız \ (backslash) ya da ' (tek tırnak) arka tarafa işlenen SQL ifadesi hakkında bizi bilgi sahibi yapmaktadır. Bu yüzden ezbere iş yapmıyoruz...
Karşımızda id değeri alan bir input var, id değerleri her tabloda default olarak gelen bir primary keydir. Integer bir değerdir ve her veri eklendiğinde otomatik olarak 1 artarak atanır. Tabi bu default olarak böyledir genelde kimse bu yapıyı bozmaz. 1 tabloda sadece 1 tane primary key vardır.
Bizden aldığı değeri veritabanından sorguluyor ve tutan id değeri ile alakalı sonucu bize döndürmekte. Arka tarafta dönen sorgu muhtemelen şöyle bir şey.
ya da
bu şekilde olmalı. id değeri integer olduğu için iki türlü de kullanabilir geliştirici. Mesele bu olasılıkları düşünmekte, eğer bunu bilemezsek SQL Injection yapamayız. Anlamamız gerek...
SQL Bilmek Önemli
SQL Injection var olan bir sorguyu genişletmeye sorguyu manipüle etmeye yönelik bir saldırıdır. Eğer SQL bilgimiz zayıf olursa yaratıcılık düşer, ezbere işler yapılır önümüze gelecek farklı bir sorguda afallayabiliriz. Union based SQL Injection yapacağız ama neden ? Neden subquery yapmıyoruz ya da yapamıyoruz ? Bu nedenler çoğalabilir, sadece SQL bilmek yetmez ayrıca karşı tarafta ne tür bir veritabanı varsa veritabanının methodlarını, mimarisini ve özelliklerini bilmek gerek. Çünkü sadece SQL kullanmıyoruz aynı zamanda o veritabanını da kullanıyoruz.
Union based SQL Injection yapıyoruz çünkü Union operatörü bize ilk sorgudan çıkan sonuçlar ile ikinci sorgudan çıkan sonuçları birleştirmemize olanak sağlıyor. Ama bir takım şartları var..
- İlk sorgudaki column sayısı ile ikinci sorgudaki column sayısı eşit olmalı
- Order by kullanılacaksa ortak column namelere sahip olma şartı
Column sayısı yani sütun sayısı yazılan sorguya göre değişiklik gösterir. Select ile kaç tane column seçilmişse o column sayısıdır. Eğer Select * ifadesi kullanılmışsa bu bize doğrudan tablonun column sayısı verir haliyle. Union Based SQL Injection'ın ilk şartı column sayısını bilmek oluyor bu yüzden.
Column (Sütun) Sayısı
Column sayısını bulmamız için 2 operatörden yararlanıyoruz. Tabi bu 2 operatör hackerların column sayısını bulması için oluşturulmamış.. Bu operatörlerin ortak bir kullanımı var.
- Order By (verilen column ile sıralama yapar)
- Group By (verilen columnu gruplar)
Bu iki birbirinden farklı operatörün bir de şöyle bir kullanımı var.
Eğer XX. column a göre sıralama yap dersek, XX kadar columnun var olması demek oluyor bu. Eğer yoksa hata verecektir sorgu. Deneyelim...
Görüldüğü gibi 1 verdik ve sorgumuz çalıştı. sonuna koyduğumuz # comment için. # işaretinden sonra ne gelirse gelsin comment olarak algılancak ve işlemeyecektir. Sorgumuzun düzgün çalışması ve manipülasyonu için comment operatörlerini bilmek gerek.
SQL de 2 adet operatör var yorum satırları için.
-- ve /* */ operatörleri. İlk operatör tek satır için ikinci operatör ise birden fazla satır için kullanılmakta. # ise mysqle özel bir operatör yine tek satırı yorum satırı yapmak için kullanılıyor.
Burası önemli :
-- kullanımına dikkat etmek gerekir.
-- kullanırken sonuna bir boşluk koymanız gerekir. Eğer sorgudan gelen ' tek tırnak işareti --' gibi bir durum oluşturursa yorum satırı işe yaramaz.
# için aynı şey geçerli değildir. #' gibi bir durumda dahi kendisinden sonra gelen her şey yorum satırı olacaktır.
order by sorgumuzu 1 arttırarak doğru sayıyı buluyoruz. Doğru sayı 2 ise biz 3 yaptığımızda hata verecektir.
Doğru sayımız 2 . Select içerisine muhtemelen 2 column yazıldı.
Tabloları Çekelim
İlk union select sorgumuzu yazıyoruz. Tam olarak şöyle bir sorgu:Görüldüğü gibi önümüze 2 sonuç geldi ama neden ? İlk sonuç ilk sorgudan geldi çünkü biz 1 verdiğimizde ortaya bir sonuç çıkıyordu. 99 verseydik 1 sonuç çıkacaktı o da 2. sorgudan gelen sonuç..
Gördünüz mü ? Union operatörünün görevi sonuçları birleştirmek. Peki biz neden select 1,2 yazdık ?
Selecte eğer column name verirseniz o columndaki veriyi yazar ama column name olmadığına emin olduğunuz şeyler yazarsanız print gibi echo gibi davranır ve o değerleri yazar. Daha doğrusu döndürür..
ee yani ? Yanisi şu biz bu columndan dönen değeri geliştiricinin HTML sayfasının neresine yazdırdığını bilmiyoruz... Belki de hiç yazdırmıyordur ? Olabilir.. Belki de yazdırıyordur görüldüğü gibi. Burada 2 column değerinden dönen değeri de kullanıyor çünkü Oğuz ve Bey kelimelerini ekrana yazmış durumda. Bazen 10 larca columndan sayfada görebildiğimiz 1 ya da 2 değer olabiliyor. Mesele union select ile çektiğimiz verileri sayfanın neresinde göreceğimizde.
Eğer göremeseydik bu BLIND SQL Injection olacaktı bizim için.. Göremediğimiz şeyleri farklı yöntemlerle test ede ede bulacaktık her şeyi... Neyseki dönen değeri ekrana yazıyor.
Column sayımız sınırlı kullanımda olduğu için ( 2 ) concat fonksiyonunu kullanacağız. concat ile seçtiğimiz column name değerlerinden dönen sonuçlar tek bir string içinde birleştirilir. Dilersek bu fonksiyonun yanına kendimiz de rastgele string değerleri koyarak '::' gibi dönen sonuçları bu şekilde ayrıştırabiliriz.
99' union select 'Oğuz', concat(table_name) from information_schema.tables --
sorgumuz bu şekilde şuan 1 column kullandığımız için concate gerek yok aslında. Şöyle de kullanabilirdik. İlerde lazım olcak ama.
99' union select 'Oğuz', table_name from information_schema.tables --
Sonuç ekrana sığmayacak kadar çok..
Bu sonuçlar da neyin nesi ? dersek...
Şöyle, information_schema adında veritabanımız var bu veritabanı içerisinden tables adındaki tablosundan -- information_schema.tables -- table_name adındaki column değerinin verilerini çektik. information_schema veritabanı mysql v5 ile beraber gelmiş default bir veritabanıdır. Bu veritabanı içerisinde geliştiricinin oluşturmuş olduğu tablolar ile alakalı columnlar ile alakalı alakalı çeşitli bilgiler bulunur baya fazla bilgi var aslında içerisinde. Biz şuan information_schema veritabanının içerisinden sistemde olan bütün veritabanlarının tüm tablolarının isimlerini çektik.. Ve bu çok fazla..
Peki biz sadece şuanki SQL sorgusunun kullandığı veritabanının içerisinde bulunan tabloların isimlerini nasıl çekicez ? İşte böyle:
99' union select 'Oğuz', table_name from information_schema.tables where table_schema = database() --
burada yararlandığımız 2. column ise table_schema. Bu columnda veritabanı ismi tutulur yani tablo hangi veritabanına aitse onun adı tutuluyor. database() fonksiyonu ise mevcut kullanılan veritabanı ismini verir. Yani where sorgumuz şuanki veritabanında kayıtlı tablo isimlerini almamızı sağladı..
Şuanki veritabanında 2 tablo adı varmış. guestbook ve users... Biz users'a bakalım..
Tablo İçerisindeki Sütun (Column) İsimlerini Öğrenme
Evet az çok kavradınız sanki hızlanalım direkt sorgumuz gelsin.99' union select 'Oğuz', column_name from information_schema.columns where table_name = 'users' --
column_name'in ve columns'un ve de table_name'in ne olduğunu anlamışsınızdır.. Açıklamaya gerek yok. Bu sorgumuz ile de users tablosundaki column nameleri (sütun isimlerini) öğrendik.
Sonuç :
En Güzel An
En güzel ana geldik çünkü artık elimizde veriyi çekebilmemiz için gerekli olan her şey var. Artık her şeyi biliyoruz tablo adlarını ve seçtiğimiz tablodaki column nameleri. Şimdi sıra herkesin bildiği o en basit sorguda tabi bir farkla concat fonksiyonu ile column limiti olduğu için string birleştirme yapacağız.
99' union select 'En Güzel An', concat(user_id,'::', first_name, '::', last_name, '::', user, '::', password, '::', avatar) from users --
Hacked x)
Verilerin arasının :: ile ayrıldığını görebilirsiniz..
MYSQL V5.0.2 ve Üstü Olmasaydı Ne Olacaktı ?
information_schema veritabanımız olmayacaktı ve yararlandığımız özelliklerinden mahrum kalacaktık. Blind SQL Injectiondaki gibi ya da tahmin ederek tablo adlarını bulacaktık, column adını bulacaktık gibi uğraş dur...
SON
Üzerinde manipülasyon yaptığımız SQL sorgusu buydu:MYSQL veritabanına SQL Injection yapmadan evvel mutlaka versiyonunu sorgulayın..
Bir sonraki yazıda görüşmek üzere esen kalın :+)
0 yorum:
Yorum Gönder