Web for Pentester 2 – SQL Injections Çözümleri

Daha önce PentesterLab’ın hazırladığı Web for Pentester 1’i çözerken oldukça keyif almıştım. (Yav he he..) Birazda kafa karıştırıcı olan problemlerde elbette mevcuttu. Bende bu keyifli uğraşımı yazıya dökmeye karar verdim. Bu sayede blog yazısı olması nedeniyle bulduğum çözümleri açıklama ihtiyacı duyacak ve daha fazla öğrenme fırsatı yakalayacağım hemde anlaşılamayan yerlerde belki birilerine ufakta olsa yardımım dokunur.

2. Deney Labının SQL Injection bölümünün çözümlerine sırasıyla başlayalım.

Example 1

Giriş noktalarına özel karakter() girerek hemen zafiyeti araştıralım. Hop hata çıktısı ekranda.

Oldukça klasik olan zafiyet giriş noktalarından alınan değerin kontrolsüzce Sql sorgusu içine konulması ve hata çıktısının ekrana bastırılması. Tek tırnak() ile “username” girdisini sonlandırıyorum ve sorgunun başarılı olması için her zaman true dönecek bir değişken yolluyorum. Sorgunun geri kalan kısmını ise yorum olarak belirtiyorum.

Attack Payload: ‘ or 1#

Sorgu: SELECT * FROM users WHERE username=’‘ or 1#‘ AND password=”

Example 2

Yine tek tırnak ile sorguyu bozmaya çalışıyorum ve hata mesajı yine ekranda. Zafiyetimiz yukarıdakiyle aynı şekilde. Payload’u denediğimizde giriş yapamadığımızı görüyoruz ancak SQLi zafiyetimiz mevcut. Burada aklımıza gelecek olan şey geri dönen sonucun tekil olması istenmiş. Biz her zaman doğru sonucu verecek birden çok kayıt döndürüyoruz. LIMIT özelliğini kullanarak tek bir kayıt döndüreceğiz. Hadi payload’umuzu geliştirelim.

Attack Payload: ‘ or 1 LIMIT 1#

Sorgu: SELECT * FROM users WHERE username=’‘ or 1 LIMIT 1#‘ AND password=”

Example 3

Input olarak tek veya çift tırnak gönderdiğimizde hiçbir tepki olmadığını görüyoruz. Demekki geliştiricimiz biraz daha akıllıca davrandı ve bu özel karakterleri filtreledi. Burada back-slash(\) kullanarak sorguyu bozmamız gerekiyor. Back-slash ile sorguda tırnak işaretinden kaçınabiliriz. Aşağıda username alanına bu karakteri gönderdiğimizde sonuçlara bakalım.

Sorguyu şu anda bozduk. SQL’in bunu nasıl yorumladığını görmenizi istiyorum. username girdisi olarak kırmızı işaretli yeri almaya çalıştı. Haliyle tırnak fazlalığından dolayı hata verdi.

SELECT * FROM users WHERE username=’\’ AND password=

Payload’umuzu geliştirmeye devam edelim ve password alanına şöyle bir girdi verelim: or 1# Ve boom!

Attack Payload: username=\ password=or 1#

Sorgu: SELECT * FROM users WHERE username=’\‘ AND password=’or 1#

Example 4

URL query üzerinden alınan parametre kontrolsüz bir şekilde sorgu içinde kullanılıyor. Oldukça basit bir payload ile tüm tabloyu çekebiliriz.

Attack Payload: ?username=” or 1

Example 5

Bu alıştırmada parametre olarak limit değerinin alındığını görüyoruz. Tırnak işareti yollayıp sorguyu bozalım. (limit=1′)

Hayal ettiğimiz gibi sorgumuz LIMIT içeriyor. UNION sayesinde yeni bir sorgu yazıp sonucu birleştirebiliriz.

Attack Payload: ?limit=3%20union%20select%20%2A%20from%20users

Sorgu: SELECT * FROM users LIMIT 3 union select * from users;

Example 6

Tırnak ile sorguyu bozuyoruz.

Bu sefer sorguda GROUP BY kullanıldığını görüyoruz. Burada aslında group parametresi atılırsa veritabanı dump edilebiliyor. Ama biz bunu es geçelim. Yine union sayesinde ikinci bir sorgu ekleyip sonuçları birleştirebiliriz. ?union select * from users şeklinde bir parametre gönderelim.

Attack Payload1: ?union%20select%20%2A%20from%20users

Attack Payload2: Parametre göndermemek.

Example 7

Tırnak işareti göndererek sorguyu bozuyoruz ve yine hata mesajımız ekranda.

Aslında yukarıdaki sorgulardan pek bir farkı olmadığını görüyoruz ve hemen union ile ikinci bir sorgu yazıyoruz. (union select * from users)

Bir kontrolle karşı karşıyayız. Sorgu sonucunun tek bir sonuç getirmesi isteniyor.

İlginç bir şekilde “id” parametresini sildiğimizde veritabanı dump ediliyor. Tüm tabloları dump etmek için daha karmaşık vektörleri içerisinde barındıran Sqlmap aracı ile deneme yapalım.

Sonuç olarak tüm tabloları çekmeyi başardık.

Example 8

Bu örnekte bir kullanıcı oluşturma ekranıyla karşı karşıyayız. Username ve password girdiğimizde veritabanına kaydedilip ardından ekranda username ve id değerlerinin çekilip gösterildiğini görüyoruz.

Hemen veritabanına kayıt olduğu için ilk sorguyu bozmaya çalışalım. Aşağıdaki gibi bir sorgu hayal ediyorum:

User input noktasına tek tırnak() atıyorum ve bir hata oluşmadığını görüyorum. Ama id kısmına tıkladığımızda;

 şeklinde bir hata döndü ve sorgu açıkça görülüyor.

Buradan anlamamız gereken veritabanında kayıtlı olan User değerlerine güvenilmiş. O zaman kaydolurken User alanına payload’umuzu yerleştireceğiz. Bu sayede eğer veritabanında boş kayıt yoksa bize ilk kullanıcının bilgilerini getirecek.

Attack Payload: User=‘ or 1 #

Example 9

Burada tüm kontrolleri yaptıktan sonra hiçbir tepkinin olmadığını görüyoruz. mysql_real_escape_string() fonksiyonu kullanıldığını hayal ederek tırnak işaretini bu fonksiyondan nasıl bypass edeceğimizi araştırıyoruz. Sonuç olarak GBK charset kullanılırsa “¿\” şeklinde bir karakterin tek karakter olarak algılandığını görüyoruz. mysql_real_escape_string() metodunun yaptığı görevi hatırlayalım.. Özel karakterlere “\” ekliyor. Örneğin tek tırnak() gönderdiğimizde bunu \’ haline getiriyor. İşte burada biz parametre olarak ¿’ göndersek ne mi olur? 🙂 Metod tek tırnağın önüne escape atar daha sonra GBK charseti ¿\‘ kısmını tek karakter olarak algılar ve tırnak işaretini geçirmiş oluruz!

¿ encode hali = %bf

‘ encode hali = %27

Attack Payload: ?username=%bf%27 or 1 %23&password=ds&submit=Gönder

Bu konu hakkında detaylı bir blog yazısı Ömer Çıtak tarafından paylaşılmış. İncelenmesi faydalı olacaktır.

Injection Saldırılarında mysql_real_escape_string ve addslashes Bypass

Web for Pentester 2’nin SQL Injection çözümlerini kendimce anlattım. Umarım faydalı olmuştur..

 

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir