Categories
OWASP PortSwigger Vulnerability

SQL Injection – Lab #13 Visible error-based SQL Injection

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.

Lab uygulama ekran görüntüsü

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.

Burp Suite Proxy – HTTP history ekran görüntüsü

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.

GET isteğinin Repeater’a gönderilmesi ekran görüntüsü

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

200 OK ekran görüntüsü

(‘) 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.

SQL sorgusunun göründüğü ekran görüntüsü
SQL sorgusunun Render tabında olan çıktının ekran görüntüsü

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. )

Yorum satırı eklendiğinde alınan 200 OK ekran görüntüsü

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.

Hata ekran görüntüsü
TrackingId=htTS7Oklz6w0Aty2' AND 1=CAST((SELECT 1) AS int)--
Boolean ifadesinin eklendiği; “=” ifadesinin kullanıldığı ekran görüntüsü

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)--
USERS tablosundaki username bilgilerinin çekilmek istendiği ekran görüntüsü

İ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.

TrackingId değerinin silinmesi sonucu oluşan hata ekran görüntüsü

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.

Kullanıcı isminin çekildiği ekran görüntüsü

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

Parola bilgisinin çekildiği ekran görüntüsü
Başarılı login ekran görüntüsü
8wal3c5p7a3tos0v5p4w //Parola

Leave a Reply

Your email address will not be published. Required fields are marked *