2013年2月7日木曜日

CTF Challenge Japan(Final) Write Ups - Service Attack 200

以下が問題文で、実際には特定のサーバに設けられているtest.cgiから解答を得てくることになる。
[タイトル]
Email のログを盗み出せ!

[問題]
サーバ管理者のA君は、どこからでもSMTPのログを確認したかったため、一見なんの変哲もないプログラムtest.cgiにEmailのログを出力する仕組みを実装した。たまたまtest.cgiを手に入れたB君はあなたにそのプログラムの解析を依頼してきた。test.cgiを解析し、サーバにあるEmailのログを得よ。
ただし、test.cgiはバイナリ形式で提供されていて、リバースエンジニアリングを行うことが可能な状態だった。
まずは test.cgiをバイナリエディタで開いてみる。


Linux用のELFバイナリのようだ。

とりあえず動かしてみる。


"Hello World!"と表示するプログラムのようだ。問題文には「Emailのログを出力するしくみを実装」とあるので、ディスアセンブラを起動して、文字列抽出結果の相互参照などから、関連しそうな箇所を調査してみる。



すると、Emailログの読み出しをしている関数が特定できた。
次に、この関数を参照している箇所を特定すると、2ヶ所存在した。ひとつは、環境変数REMOTE_ADDRを確認する関数。もう一つはQUERY_STRINGを確認するものだった。


通常、REMOTE_ADDRは、アクセス元のIPアドレスを得るための環境変数として使われており、このプログラムにおいても同様であった。しかも、ローカルのループバックアドレスからのアクセスということは、このCGIプログラムの設置されているサーバに何らかの方法で侵入した上で、このプログラムにアクセスすることが、電子メールアドレスの中身を見る方法となる。

でも、この方法を使えるチャンスはなさそうだ。

そこで、QUERY_STRINGを確認するコードを確認する。password.txtを開いて、その中の文字列を読み出してパラメータとして入力した文字列とのマッチングを行う、いわばパスワード認証を行うようだ。


パスワードを辞書攻撃したり、総当たりするのもいいが、それでは時間が足りなくなってしまう。
この関数に渡される、パラメータの受け渡し部分を確認してみる。


ここに脆弱性があるようだ。このプログラムはパラメータとして16文字までのデータを処理するようにコーディングされている。ESPレジスタの値を起点にして、パラメータとして受け取った文字列をローカル変数として確保した領域にコピーするが、その際の計算ミスで1バイトだけ、スタックのリターンアドレスを書き換えることができる。


上書きできるリターンアドレスは1バイトだけなので、このプログラムの場合0x08048600~0x080486ffの範囲でジャンプ先を指定できることになる。


Emailのログデータを読み出す関数のエントリポイントは0x08048651なので、リターンアドレスを1バイトだけ書き換える値を0x51にしてあれば、ここにジャンプできることになり、パスワード認証を迂回できることになる。


どうやらこれが解答のようだ。