Görünen SQL Hatasını İstismar Etmek
Burada kullanılan SQL database’nin vermiş olduğu hatalardan yola çıkarak veri çekmeye çalışacağız. Hatada SQL isteklerinin direkt olarak görünmesi zafiyeti bu başlıkta değerlendirilmektedir. Bu örnekte elimizdeki bilgiler “USERS” adında bir tablonun olduğu ve bu tabloda “USERNAME” ve “PASSWORD” sütunlarının bulunduğudur.

Uygulama üzerinde gezinirken görünürde karşımıza bir hata vb. çıktı gelmiyor. Burp Suite ile araya giriyor ve giden paketleri incelemeye başlıyoruz. Burp Suite üzerinde Proxy – HTTP history menüsünden giden GET isteklerini incelemeye başlıyoruz.

Menülerde gezerken GET isteklerinde “TrackingId” adında bir değerin hep aynı döndüğünü görüyoruz ve bunu istismar edebilir miyiz ona bakıyoruz. GET isteğine sağ click yapıp Repeater’a gönderiyoruz.

İstek 200 OK döndüğünde aşağıdaki ekran görüntüsü alınmaktadır.

(‘) tırnak işareti ile istediği bozduğumuzda “500 Internal Server Error” hatası alıyoruz. Aynı zamanda ekrana SQL sorgusununda geldiğini görüyoruz.


Gönderdiğimiz sorguyu farklı değerler atayarak yeniden gönderiyoruz. “AND”, “–“, “OR” gibi deneler yapıyoruz ve bu defa sunucu hatası almadığımızı görüyoruz. Bu durumda dogru sorgu ile veri çekebileceğimizi öngörüyoruz. (Makalede yer alan ekran görüntülerindeki TrackingId değerinin değişme nedeni farklı zamanlarda aldığım ekranlar yüzündendir. )

Biz “TrackingId” ile çalışma yapıyoruz. Bu da bir kimlik, benzersiz bir değer olarak görünüyor ve integer veri döndürmesini bekliyoruz. Bu bilgi SQL sorgunu belirlemek için önemlidir. Eğer isim, eposta gibi bir değerle çalışsaydık o zaman databese bize string değer dönecekti. Bizde SQL sorgumuzu ona göre hazırlayacaktık.
Genel bir SELECT isteği atacağız. Integer veri dönmesi için CAST fonksiyonundan yararlanacağız. Bkz.
TrackingId=htTS7Oklz6w0Aty2' AND CAST((SELECT 1) AS int)--
İsteği gönderdiğimizde AND ifadesine kızdığını ve bunun bir boolean ifadesi olmadığını görüyoruz. Bkz.

TrackingId=htTS7Oklz6w0Aty2' AND 1=CAST((SELECT 1) AS int)--

Burada CAST fonksiyonunu 2 ile eşitledik ama rakamın önemi yok. 2-3 vb. olabilir. Sonuçta 200 OK dönüyor olması yeterlidir. Artık sorgumuzdan hata almadığımıza göre SELECT kısmını elimizdeki bilgiler ışında güncelleyerek sorgumuzu yeniden gönderiyoruz.
TrackingId=htTS7Oklz6w0Aty2' AND 2=CAST((SELECT username FROM users) AS int)--

İlk tek tırnak (‘) gönderdiğimizdeki hataya benzer bir hata alıyoruz. Karakter ifadesi olduğu için “TrackingId” değerini silip yeniden istek atıyoruz. Yine “500 Internal Server Error” almamıza rağmen ekrana yansıyan hatanın değiştiğini görüyoruz.

Hata mesajında birden fazla satır döndüğünü belirtiyor. Yeniden sorgumuzu düzenliyoruz. Daha önce de benzer işlemler yapmıştık. “LIMIT” değeri ekleyerek yeniden sorgumuzu oluşturuyoruz.
TrackingId=' AND 2=CAST((SELECT username FROM users LIMIT 1) AS int)--
Yukarıdaki sorguyu gönderdiğimizde “500 Internal Server Error” hatası alıyoruz fakat sayfada aşağı indiğimizde bize bir kullanıcı adı da döndürdüğünü görüyoruz.

Sorgumuzu USERS tablosundaki PASSWORD sütununu verecek şekilde yeniden düzenliyoruz ve parolayı ele geçirerek sisteme admin seviyesinde login olmayı başarıyoruz.


8wal3c5p7a3tos0v5p4w //Parola