[タイトル]ただし、test.cgiはバイナリ形式で提供されていて、リバースエンジニアリングを行うことが可能な状態だった。
Email のログを盗み出せ!
[問題]
サーバ管理者のA君は、どこからでもSMTPのログを確認したかったため、一見なんの変哲もないプログラムtest.cgiにEmailのログを出力する仕組みを実装した。たまたまtest.cgiを手に入れたB君はあなたにそのプログラムの解析を依頼してきた。test.cgiを解析し、サーバにあるEmailのログを得よ。
まずは test.cgiをバイナリエディタで開いてみる。
Linux用のELFバイナリのようだ。
とりあえず動かしてみる。
"Hello World!"と表示するプログラムのようだ。問題文には「Emailのログを出力するしくみを実装」とあるので、ディスアセンブラを起動して、文字列抽出結果の相互参照などから、関連しそうな箇所を調査してみる。
すると、Emailログの読み出しをしている関数が特定できた。
次に、この関数を参照している箇所を特定すると、2ヶ所存在した。ひとつは、環境変数REMOTE_ADDRを確認する関数。もう一つはQUERY_STRINGを確認するものだった。
通常、REMOTE_ADDRは、アクセス元のIPアドレスを得るための環境変数として使われており、このプログラムにおいても同様であった。しかも、ローカルのループバックアドレスからのアクセスということは、このCGIプログラムの設置されているサーバに何らかの方法で侵入した上で、このプログラムにアクセスすることが、電子メールアドレスの中身を見る方法となる。
でも、この方法を使えるチャンスはなさそうだ。
そこで、QUERY_STRINGを確認するコードを確認する。password.txtを開いて、その中の文字列を読み出してパラメータとして入力した文字列とのマッチングを行う、いわばパスワード認証を行うようだ。
パスワードを辞書攻撃したり、総当たりするのもいいが、それでは時間が足りなくなってしまう。
この関数に渡される、パラメータの受け渡し部分を確認してみる。
ここに脆弱性があるようだ。このプログラムはパラメータとして16文字までのデータを処理するようにコーディングされている。ESPレジスタの値を起点にして、パラメータとして受け取った文字列をローカル変数として確保した領域にコピーするが、その際の計算ミスで1バイトだけ、スタックのリターンアドレスを書き換えることができる。
Emailのログデータを読み出す関数のエントリポイントは0x08048651なので、リターンアドレスを1バイトだけ書き換える値を0x51にしてあれば、ここにジャンプできることになり、パスワード認証を迂回できることになる。
どうやらこれが解答のようだ。