DVWA-SQL Injection Çözümleri

Sefa Ozan
6 min readApr 13, 2021

--

Herkese merhaba, DVWA lablarını çözdüğümüz serinin üçüncüsüne hoş geldiniz. Bu yazımda sizlere elimden geldiğince SQL Injection zafiyetinin ne olduğu ve nasıl sömürebileceğiniz göstereceğim.

#KOLAY

SQLi aramaya, geleneksel tırnak atma festivali ile başlıyoruz.

Submit’e bastığımızda. SQL error ile karşılaşıyoruz.

Hata almamızın sebebi arka planda SELECT * FROM USERS WHERE USER_ID = '<USER_INPUT>' gibi bir SQL sorgusunun olmasıdır. Biz ' yazıp submit’e bastığımızda yeni SQL sorgumuz SELECT * FROM USERS WHERE USER_ID = ''' böyle oluyor. Oradaki fazlalık bir tane tırnak hataya neden oluyor.

NOT : Burada asıl oluşan hatayı görebilmemiz değil çünkü devoloperlar istese hatayı bize döndürmeyedebilirdi. Burada asıl olay başlangıç noktamızdan farklı bir yere gitmemiz.

Başlangıç noktamıza geri dönebilmemiz için oluşturduğumuz bu hatayı gidermemiz gerekiyor. Burada devreye, kodlarımızı yorum satırına çevirmeye yarayan özel işaretler giriyor.

Payload’ımızı ' --olarak değiştirip submit’e basıyoruz.

Hala hata almaya devam ediyoruz.

Bu örnek için oluşan hata sayesinde arka planda çalışan database’in MySQL olduğunu görebiliyoruz. Biz böyle bir hatanın oluşmadığını dolayısıyla da hangi database’in kullanıldığını görmediğimizi farz edelim ve uygulamanın hangi database’i kullandığını bulmaya çalışalım.

Payload’ımızı ' -- olarak değiştirip yolladığımızda hata almaya devam ediyorduk. O halde payload’ımzın sonuna bir boşluk koyalım ve tekrar submite basalım. Eğer başlangıç noktamıza geri dönebilirsek arka planda çalışan databasenin MySQL olduğunu kanıtlayabiliriz.

Ve artık hata almıyoruz. Daha da önemlisi başlangıç noktamıza dönebildik.

Şimdi kendi SQL sorgumuzu yazmaya başlayabiliriz. Kendi SQL sorgumuzu yazabilmemiz için UNION operandını kullanacağız. UNION operandını kullanabilmek için iki şart gereklidir.

  • Her iki query’nin de kolon sayısı eşit olmalıdır.
  • Her iki query’ideki colonların dataların türleri birbirlerine dönüştürülebir olmalıdır.

Yeni payload’ımızı yazıp submit’e bastığımızda yine hata ile karşılaşıyoruz. çünkü bizim görmediğimiz, bizden önceki SQL sorgusu ile bizim kolon sayılarımız eşit değil.

NOT : null yazmamın sebebi null hem string’e hem de integer’a dönüştürülebilir.

Kolon sayıları eşit olana kadar null eklemeye devam edeceğiz.

Bir kez daha başlangıç noktamıza geri dönebildik.

Firt name ve Surname‘in boş olmasının sebebi null yazmamız. Şimdi sırada kolonlardan hangisinin string hangisinin integer değer alabildiğini inceleyeceğiz.

Yukarıda gördüğünüz gibi her ikisi de string değer alabiliyor.

' union select table_name,'b' from information_schema.tables where table_schema = database() --

  • information_schema.tables : Database’deki bütün tablolarının tutulduğu yer.
  • table_schema = database(): Tablo şemasının, mevcuttaki database’e eşit olanlarını getiririr

Sorgumuz başarılı bir şekilde çalıştı ve tablo isimlerini çekebildik. Şimdi sırada kolon isimleri var.

' union select column_name,'b' from information_schema.columns where table_name = 'users' --

  • information_schema.tables : Database’deki bütün tablolarının tutulduğu yer.
  • where table_name = 'users': Tablo ismi users olan tabloyu getir

Kolon isimlerini de başarılı bir şekilde çektiğimize göre artık user ve password kolonlarında neler var öğrenebiliriz.

' union select user,password from users --

#ORTA

Herhangi bir input girebileceğimiz yer yok ama User ID kısmını biz yönetiyoruz.

O halde Burp Suite ile bir request yakalayıp Repeater’a gönderelim.

id parametresinin sonuna tırnak atarak SQLi aramaya başlıyoruz.

Gördüğünüz gibi SQL syntax hatası aldık.

Hatadan kurtulabilmek, başladığımız yere geri dönebilmek için; bozduğumuz syntax’i düzeltmemiz gerekiyor. Bunuda id parametresinin sonuna --yorum satırı ekleyerek yapıyoruz.

Gördüğünüz gibi hala hata almaya devam ediyoruz.

Hatayı gidermeye bayağı bir süre uğraştıktan sonra sorunun tek tırnakta ' olduğuna kanaat getirdim. Tek tırnaksız yaptığım sorgularda hata almıyordum artık.

Bizden önceki sorguda kaç tane kolon kullanıldığını bulma aşamamıza geçiyoruz.

Bir önceki sorguda kullanılan kolon sayısı ile bizim kolon sayımız uyuşmuyor.

Gördüğünüz gibi başlangıç noktamıza geri dönebildik. Demek ki bizden önceki sorguda iki tane kolon kullanılmış.

Hangi satırların string değer alabileceğini anlamak için normalde her kolona ayrı ayrı string ifadeler yazarız. Ben de bu yüzden 'testdeneme' yazmıştım ama bu örnek için tek tırnağı ' kullanamadığımızdan dolayı işe yaramayacak.

2' union select null,table_name from information_schema.tables where table_schema = database() --

Başarılı bir şekilde tablo isimlerini çektik. Şimdi sırada kolon isimleri var.

2' union select null,column_name from information_schema.columns where table_schema = database() --

  • Normalde burada table_name ='<table name>' olması gerekiyordu ama tırnak işaretlerini kullanamadığım için table_schema=database() olarak bıraktım.

Kolon isimlerini de başarılı bir şekilde çektiğimize göre artık user ve password kolonlarında neler var öğrenebiliriz.

CONCAT : String verileri birleştirmeye yarar. Ben de burada username ve password’ü tek bir kolon üzerinden çekmeye çalıştım ama pek başarılı olamadım çünkü aşağıdaki resimden de görebileceğiniz gibi username ve passwordler birbirine girdi. Normalde concat, CONCAT(user,'*::::*',password)gibi regexler ile birlikte kullanılır. Biz ' kullanamadığımız için concat konusunda başarısız olduk.

Ben de user ve password kolonlarını teker teker çekme kararı aldım.

#ZOR

Her zamanki gibi tırnak atarak başlıyoruz.

Gördüğünüz gibi başlangıç noktamızdan farklı bir yere yönlendirildik.

Başlangıç noktamıza geri dönebilmemiz için yorum satırı ekliyoruz.

Başlangıç noktamıza geri dönebildik.

Kolon sayımızı buluyoruz.

Kolon sayımızı bulduğumuza göre tablo isimlerini çekebiliriz.

Şimdi de kolon isimlerini çekebiliriz.

' union select null,CONCAT(user,'*::::::*',password) from users --

Bir sonraki yazımda görüşmek üzere …

--

--

Sefa Ozan
Sefa Ozan

No responses yet