今回はHackme Lv2の攻略。
以下、Hackmeの攻略に関するネタバレを多大に含みます。自力で攻略したいなら見ちゃだめです。
[Lv2]
1.ヒントを探す
今回もまた、ページを眺めてみてもこれといった発見はない。右クリックもできる。
ソースコードにもアカウント情報は記載されていない(当然といえば当然だが)
物は試しとLv1と同じ情報を入力してみると・・・
「ユーザ名またはパスワードが違います」というエラーメッセージが表示された。
そういえば、たまにパスワードだけが間違っているって表示しちゃうサイトがあるが、
それって結構危ないんだよな。IDはデータベース上に存在してるって自分で証明してるわけだから。
Lv2さんはそんなに甘くないってことだな。流石や!
2.考える
さて、どうやらユーザが見ることができる範囲にヒントになるような情報はなさそうだ。
仕方がないので少し専門的な知識を使おう。
Q.Webサイトのログインフォームを作る際に注意しなければならない攻撃は?
A.SQLインジェクションです。
Q.SQLインジェクション対策として有効なのは?
A.サニタイジング処理またはバインド機構です。
という具合に、データベースとWebセキュリティの基本を知ってれば誰もが考える。
では早速検証してみよう。
3.検証する
要は、SQLにおいて意味を持つ特殊文字がどう扱われているかを調べればいいわけだ。
代表的なのはアポストロフィ(')だな。
というわけでIDをてきとーに入力し、パスワードにただ1文字 ' と入力してみる。
結果は・・・
pg_queryとかいういかにもデータベース扱ってますよと云わんばかりに命名されたメソッドでエラーが!
アポストロフィ付近で文法エラーが起きてクエリが発行できなかったと書いてある。
さっきまでクラッカーにヒントを与えない完璧なエラーメッセージを発し続けていたLv2さんが
こんな明瞭なヒントを出すなんて・・・
妙に変だなぁ・・・
プログラムでサニタイジングやプレースホルダが使われているなら、
はじめのように「ユーザ名またはパスワードが違います」と表示されるはず。
しかしSQL文法エラーが起きているという事は、入力された特殊文字がSQL文中で意味を持っているということ!
SQLインジェクションが有効だと考えられるね。
4.Hackyou!
SQLインジェクションというのは、簡単に言えばフォームにSQL文を打ち込んで実行させる手法だ。
ログインフォームでは、認証に用いられるクエリの実行結果が「true」になるようにSQL文を入力すればいい。
たとえば、↓のようなSQL文でパスワードの認証を行っているとする。
SELECT user_password FROM user_info WHERE user_password = '<入力された値>';
この一文の内、WHERE句の条件に注目する。
素直に「password = ?」の形でクラッキングを試みたところで勝算はない。
このままでは本当に存在するパスワードを入力する以外ではクエリの結果を「true」にできないからだ。
上記クエリの実行結果を「true」にするには、SQL文を↓のように書き換えて実行させればいい。
# xxxは任意の文字列
SELECT user_password FROM user_info WHERE user_password = 'xxx' OR 絶対にtrueになる式 --';
条件式にある「A OR B」という形は、「最低限AかBのどちらかがtrueなら結果もtrue」っていう意味。
だからxxxが間違っていても、後に書いた<絶対にtrueになる式>によって実行結果はtrueになる。
そして、「--」は「それ以降をコメント化(無視)する」という意味。
これをつけないと末尾に残るアポストロフィによって文法エラーになってしまう。
説明が長くなったが、そんなこんなの理由から僕が入力したのは以下の通りだ。
ID :まろ最高
Pass:a' or 1=1 --
結果は・・・
Lv2クリア!
次回はLv3の攻略。