これはログインまでいったものの、そこからが行き詰まったため、write up を見た。
そして、自分でまとめ直してみようとおもう。
これは、SQL インジェクションの問題だが、ただ 1 OR 1 = 1; --
と打てばよいものではない。
ブラインド SQL インジェクションという手法を使う。
これは、直接 SQL 実行結果をみることはできずとも、クエリを実行した後の様子を観察することで情報を取得するもの。
今回の問題ではまさに SQL の実行結果をみることはできない。
しかし、ログインできたかどうかがわかる。
この「ログインできたかどうか」を使って、FLAG の奪取を目指す。
今回普通に SQL インジェクションでログインを試みると、普通に入ることができる。
しかし、そこにはログインはできたものの、「FLAG は admin ユーザーの password だよ」と知らされる。
ここから、なんとかして password を表示させたいが、実行結果を表示させるよな機構がないため上手くいかない。
そこで上記の「ブラインド SQL インジェクション」である。
1 OR 1 = 1; --
このテキストを入力するとログインできるのは、1 = 1
が true であるから。
つまり、ここが true になればなんでもよい。
この1 = 1
を、(SELECT LENGTH(pass) FROM user WHERE id = 'admin') > 1
と置き換えてみる(id が admin なのは、問題で公開されてる情報)
こうすると、admin の pass の文字列の長さが 1 より大きければ true、 つまりログインできるということになる。
これを使って、ログインできるかできないかを見ながら pass の長さが特定できる。
さらに、これを使って pass 自身も特定することができる。
SQL には SUBSTR というクエリがある(今回初めて知った)
これは、文字を切り取る関数で、開始位置と切り取り文字数を指定する。
これを使って、例えば
' or SUBSTR((SELECT pass FROM user WHERE id = 'admin'), 1, 1) = 'F' --
インジェクションする文字列をこのようにすれば、1 番目の文字が F であればログインできる、ということになる。
あとはこれを繰り返せば password が特定できると言うわけだ。(感動しました)
もちろんスクリプトを書いてやる。