I.Blind SQL Injection (Content Based)
SQL Injection açıklığı UNION tekniği ile farklı tablolardan veri sızdırmamıza imkan vermiyorsa, ancak injection'ı yaptığımız noktada AND operatörü sonrasında oluşturacağımız TRUE ve FALSE koşullarına karşı farklı yanıtlar üretiyorsa, o halde bir şansımız daha var demektir.
UNION tabanlı veya doğrudan yanıt doğuran yöntemlere nazaran çok daha fazla sayıda istek göndermemiz gerekecektir.
Blind SQL Injection yönteminde genellikle veriler harf harf belirlenir ve her bir harfin değerini bulmak
için binary search yöntemi kullanılır. Örneğin 0-100 arasında bulunması gereken 83 değerini bulmak için önce değerin 50'den büyük olup olmadığını sorgularsınız, eğer büyükse bu sefer 75'ten büyük olup
olmadığını sorgularsınız, bundan da büyükse 88'den büyük olup olmadığını sorgularsınız. Bu sayıdan büyük olmadığı için bu defa 75 ve 88 sayılarının ortasında bulunan 81'den büyük olup olmadığını sorgularsınız ve bu sayı bulununcaya kadar devam eder.
II.Blind SQL Injection (Content-Based) Örneği
Content Base Blind SQL Injection örneği için uygulamamızın Şifre Değiştirme fonksiyonundan yararlanmaya çalışacağız
Form alanlarından görünür olanları Mevcut Şifre ve Yeni Şifre alanları
Bundan sonraki adımlarda şifre değişiklik işleminde mevcut şifre hatalı durumuna düşmemek için (uygulamanın yeni şifrenin eski şifre ile aynı olup olmadığını kontrol etmemesinden de faydalanarak) şifremizi 123456 olarak değiştiriyoruz
Şifremiz 123456 olarak değiştirildi.
Ancak formu gönderdiğimizde form alanlarının tamamı görünenlerden mi ibaret, inceleyelim.
Bu işlem için bir atak proxy olan Burp Suite aracından faydalanacağız. Bu araç ile trafiği keserek giden ve gelen isteklerdeki form alanlarını inceleme fırsatımız olacak.
Tarayıcımızdan proxy ayarımızı yaptıkdan sonra istekler Burp üzerinden geçerek sunucuya iletilecektir. Bu işlem için internet tarayıcımızın proxy ayarı aşağıdaki şekilde yapılmalıdır.
Bu adımdan sonra şifre değiştirme ekranında tekrar işlem yapalım ve Burp üzerinde bu isteği inceleyelim.
Bu aşamada, giden parametreler arasında bir de "kullanicino" parametresinin bulunduğunu görüyoruz.
Bu parametreyi tırnak işareti değeri ile ilettiğimizde ne olacağını gözlemleyelim. Bu sayede sisteme hata aldırıp aldırılamadığı gözlemlenebilir.
Hatalı bir durum oluştu, ancak uygulama hatayı ele aldı. SQL Injection olma ihtimali yüksek, ancak hata mesajı olmadığı için farklı bir neden de olabilir. Elde ettiğimiz bu ipucuna biraz daha odaklanalım.
Bu isteğin üzerinde daha rahat çalışabilmek için isteği Burp’ün "Repeater" modülüne atalım. Bu modül ile aynı istek üzerinde değişiklik yapıp sunucuya göndererek yanıtları inceleyebiliriz. İstek üzerinde sağ tıklayıp açılan pencerede “Send To Repeater” tıklamamız yeterli olacaktır.
İstek parametreleri üzerinde değişiklik yaparken URL kodlama kurallarına uygunsuzluğu önlemek amacıyla Burp'ün aşağıdaki yardımcı fonksiyonunu aktif hale getirelim. Böylece yazdığımız özel karakterler Burp tarafında URL kodlama yöntemiyle yazılacaklar.
“5550000002'+AND+1%3d1--+” injection payloadu ile "kullanicino" parametresinin string tipinde olduğu varsayımında bulunarak ve geçerli bir kullanıcı kodu kullanarak doğru (TRUE) sonuç doğuracak bir sorgu oluşturmayı hedefliyoruz.
Payload eklediğimiz isteği sunucuya gönderdiğimizde aşağıdaki şekilde (TRUE) sonucunu elde edebiliyoruz.
Koşulun yanlış (FALSE) olacağı şekilde bir düzenleme yaptığımızda ise aldığımız yanıt (content) doğru koşuldan farklı olmaktadır. İşte bu aradaki fark bize veritabanına yönelik çok sayıda sorgu yaparak veri sızdırma imkanı sağlayacaktır
“5550000002'+AND+1%3d2--+” payload olarak kullanıp tekrar istek yapalım ve yanıtın doğru (TRUE) koşuldan farklı olduğuna dikkat edelim.
TRUE ve FALSE durumlarından emin olduktan sonra biraz daha kontrollü istekler gerçekleştirebiliriz.
İlk testimizde MySQL database() fonksiyonunun döndürdüğü değerin ilk karakterinin "a" (ASCII 97) olup olmadığını test ediyoruz. Test için aşağıdaki payloadu kullanabiliriz;
“5550000002'+AND+ascii(substring(database(),1,1))%3d97--+”
Kullandığımız bu payload içerisindeki substring fonksiyonu yaptığımız sorgudaki parametreler sayesinde bize database() fonksiyonundaki ilk string ifadenin ilk değerini döndürecektir.
Dönen yanıt FALSE durumunda oluşan yanıt olduğundan ilk karakterin "a" olmadığı sonucuna varabiliriz.
Bu defa "b" (ASCII 98) karakterinin doğru olup olmadığını test ediyoruz ve dönen yanıt TRUE koşulunda gözlediğimiz yanıt olduğu için database() fonksiyonunun döndürdüğü ilk karakterin "b" olduğunu söyleyebiliriz. İlgili payload;
“5550000002'+AND+ascii(substring(database(),1,1))%3d97--+”
TRUE koşulu elde ettikten sonra daha fazla bilgi elde etmek istersek sorgumuzu aşağıdaki şekilde
güncelleyebiliriz. Bu sorgu ile artık database() fonksiyonundaki ilk string değerin ikinci karakterinin “b” olup olmadığını kontrol edecek ve bize yanıt olarak döndürecektir.
“5550000002'+AND+ascii(substring(database(),1,2))%3d97--+”
Yukarıdaki örneklerde görüldüğü üzere özel sorgular hazırlanarak TRUE ve FALSE koşulların sağladığı bilgiler ile database üzerinden Blin SQL Injection saldırıları ile bilgi sızdırma imkanı doğmaktadır.
III.Blind SQL Injection (Time-Based)
Eğer SQL injection yapabilmemize ve TRUE ve FALSE koşullar oluşturabilmemize rağmen yanıtlarda bir farklılık gözlenmiyorsa o zaman TRUE veya FALSE koşullar oluştuğunda yanıtın dönme hızını etkileyerek yine veri sızdırma şansımız olabilir.
Hem çok sayıda istek göndermemiz hem de zaman farkına dayanan bir yöntem olduğu için çok daha fazla süre beklememiz gerekecektir.
Time based SQL injection yönteminde sonucun hata doğurup doğurmadığı önemli değildir, ancak belli bir koşul gerçekleştiğinde sunucunun daha geç yanıt vermesine dayanarak veriler tahmin edilir.
MySQL'e özel bir Time-Based SQL injection sorgusu;
http://www.site.com/news.php?id=5 and 1=IF(ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>80, sleep(15),1)
Veritabanı sunucularının TIME-BASED BLIND SQL INJECTION saldırılarında kullanılabilecek fonksiyonlarına örnekler:
MSSQL
• sleep(5000) (sleep fonksiyonu MySQL 5.0.12 ve sonraki versiyonlarında kullanılabilir, 5.000 milisaniye bekle anlamına gelir)
• benchmark(50000, SHA1('test')) (50.000 defa 'test' verisinin SHA1 hash değerini hesapla, bunun dışında CPU zamanını alabilecek farklı MySQL fonksiyonları da bulunmaktadır)
SQL Injection açıklığı UNION tekniği ile farklı tablolardan veri sızdırmamıza imkan vermiyorsa, ancak injection'ı yaptığımız noktada AND operatörü sonrasında oluşturacağımız TRUE ve FALSE koşullarına karşı farklı yanıtlar üretiyorsa, o halde bir şansımız daha var demektir.
UNION tabanlı veya doğrudan yanıt doğuran yöntemlere nazaran çok daha fazla sayıda istek göndermemiz gerekecektir.
Blind SQL Injection yönteminde genellikle veriler harf harf belirlenir ve her bir harfin değerini bulmak
için binary search yöntemi kullanılır. Örneğin 0-100 arasında bulunması gereken 83 değerini bulmak için önce değerin 50'den büyük olup olmadığını sorgularsınız, eğer büyükse bu sefer 75'ten büyük olup
olmadığını sorgularsınız, bundan da büyükse 88'den büyük olup olmadığını sorgularsınız. Bu sayıdan büyük olmadığı için bu defa 75 ve 88 sayılarının ortasında bulunan 81'den büyük olup olmadığını sorgularsınız ve bu sayı bulununcaya kadar devam eder.
II.Blind SQL Injection (Content-Based) Örneği
Content Base Blind SQL Injection örneği için uygulamamızın Şifre Değiştirme fonksiyonundan yararlanmaya çalışacağız
Form alanlarından görünür olanları Mevcut Şifre ve Yeni Şifre alanları
Bundan sonraki adımlarda şifre değişiklik işleminde mevcut şifre hatalı durumuna düşmemek için (uygulamanın yeni şifrenin eski şifre ile aynı olup olmadığını kontrol etmemesinden de faydalanarak) şifremizi 123456 olarak değiştiriyoruz
Şifremiz 123456 olarak değiştirildi.
Ancak formu gönderdiğimizde form alanlarının tamamı görünenlerden mi ibaret, inceleyelim.
Bu işlem için bir atak proxy olan Burp Suite aracından faydalanacağız. Bu araç ile trafiği keserek giden ve gelen isteklerdeki form alanlarını inceleme fırsatımız olacak.
Tarayıcımızdan proxy ayarımızı yaptıkdan sonra istekler Burp üzerinden geçerek sunucuya iletilecektir. Bu işlem için internet tarayıcımızın proxy ayarı aşağıdaki şekilde yapılmalıdır.
Bu adımdan sonra şifre değiştirme ekranında tekrar işlem yapalım ve Burp üzerinde bu isteği inceleyelim.
Bu aşamada, giden parametreler arasında bir de "kullanicino" parametresinin bulunduğunu görüyoruz.
Bu parametreyi tırnak işareti değeri ile ilettiğimizde ne olacağını gözlemleyelim. Bu sayede sisteme hata aldırıp aldırılamadığı gözlemlenebilir.
Hatalı bir durum oluştu, ancak uygulama hatayı ele aldı. SQL Injection olma ihtimali yüksek, ancak hata mesajı olmadığı için farklı bir neden de olabilir. Elde ettiğimiz bu ipucuna biraz daha odaklanalım.
Bu isteğin üzerinde daha rahat çalışabilmek için isteği Burp’ün "Repeater" modülüne atalım. Bu modül ile aynı istek üzerinde değişiklik yapıp sunucuya göndererek yanıtları inceleyebiliriz. İstek üzerinde sağ tıklayıp açılan pencerede “Send To Repeater” tıklamamız yeterli olacaktır.
İstek parametreleri üzerinde değişiklik yaparken URL kodlama kurallarına uygunsuzluğu önlemek amacıyla Burp'ün aşağıdaki yardımcı fonksiyonunu aktif hale getirelim. Böylece yazdığımız özel karakterler Burp tarafında URL kodlama yöntemiyle yazılacaklar.
“5550000002'+AND+1%3d1--+” injection payloadu ile "kullanicino" parametresinin string tipinde olduğu varsayımında bulunarak ve geçerli bir kullanıcı kodu kullanarak doğru (TRUE) sonuç doğuracak bir sorgu oluşturmayı hedefliyoruz.
Payload eklediğimiz isteği sunucuya gönderdiğimizde aşağıdaki şekilde (TRUE) sonucunu elde edebiliyoruz.
Koşulun yanlış (FALSE) olacağı şekilde bir düzenleme yaptığımızda ise aldığımız yanıt (content) doğru koşuldan farklı olmaktadır. İşte bu aradaki fark bize veritabanına yönelik çok sayıda sorgu yaparak veri sızdırma imkanı sağlayacaktır
“5550000002'+AND+1%3d2--+” payload olarak kullanıp tekrar istek yapalım ve yanıtın doğru (TRUE) koşuldan farklı olduğuna dikkat edelim.
TRUE ve FALSE durumlarından emin olduktan sonra biraz daha kontrollü istekler gerçekleştirebiliriz.
İlk testimizde MySQL database() fonksiyonunun döndürdüğü değerin ilk karakterinin "a" (ASCII 97) olup olmadığını test ediyoruz. Test için aşağıdaki payloadu kullanabiliriz;
“5550000002'+AND+ascii(substring(database(),1,1))%3d97--+”
Kullandığımız bu payload içerisindeki substring fonksiyonu yaptığımız sorgudaki parametreler sayesinde bize database() fonksiyonundaki ilk string ifadenin ilk değerini döndürecektir.
Dönen yanıt FALSE durumunda oluşan yanıt olduğundan ilk karakterin "a" olmadığı sonucuna varabiliriz.
Bu defa "b" (ASCII 98) karakterinin doğru olup olmadığını test ediyoruz ve dönen yanıt TRUE koşulunda gözlediğimiz yanıt olduğu için database() fonksiyonunun döndürdüğü ilk karakterin "b" olduğunu söyleyebiliriz. İlgili payload;
“5550000002'+AND+ascii(substring(database(),1,1))%3d97--+”
TRUE koşulu elde ettikten sonra daha fazla bilgi elde etmek istersek sorgumuzu aşağıdaki şekilde
güncelleyebiliriz. Bu sorgu ile artık database() fonksiyonundaki ilk string değerin ikinci karakterinin “b” olup olmadığını kontrol edecek ve bize yanıt olarak döndürecektir.
“5550000002'+AND+ascii(substring(database(),1,2))%3d97--+”
Yukarıdaki örneklerde görüldüğü üzere özel sorgular hazırlanarak TRUE ve FALSE koşulların sağladığı bilgiler ile database üzerinden Blin SQL Injection saldırıları ile bilgi sızdırma imkanı doğmaktadır.
III.Blind SQL Injection (Time-Based)
Eğer SQL injection yapabilmemize ve TRUE ve FALSE koşullar oluşturabilmemize rağmen yanıtlarda bir farklılık gözlenmiyorsa o zaman TRUE veya FALSE koşullar oluştuğunda yanıtın dönme hızını etkileyerek yine veri sızdırma şansımız olabilir.
Hem çok sayıda istek göndermemiz hem de zaman farkına dayanan bir yöntem olduğu için çok daha fazla süre beklememiz gerekecektir.
Time based SQL injection yönteminde sonucun hata doğurup doğurmadığı önemli değildir, ancak belli bir koşul gerçekleştiğinde sunucunun daha geç yanıt vermesine dayanarak veriler tahmin edilir.
MySQL'e özel bir Time-Based SQL injection sorgusu;
http://www.site.com/news.php?id=5 and 1=IF(ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>80, sleep(15),1)
Veritabanı sunucularının TIME-BASED BLIND SQL INJECTION saldırılarında kullanılabilecek fonksiyonlarına örnekler:
MSSQL
- WAITFOR DELAY '0:0:10' (10 sn. bekle)
• sleep(5000) (sleep fonksiyonu MySQL 5.0.12 ve sonraki versiyonlarında kullanılabilir, 5.000 milisaniye bekle anlamına gelir)
• benchmark(50000, SHA1('test')) (50.000 defa 'test' verisinin SHA1 hash değerini hesapla, bunun dışında CPU zamanını alabilecek farklı MySQL fonksiyonları da bulunmaktadır)