がるの健忘録

エンジニアでゲーマーで講師で占い師なおいちゃんのブログです。

不必要情報の実例とヘッジ例

許可を頂いたのである意味遠慮無くw


EC-CUBEというソフトがあります。今回の実例です。
http://www.ec-cube.net/
そうですねぇ…installして、ってのが真っ当なのでそっちで行ってみていただきたいのですが。まぁ適宜、環境などご用意くださいませ。
間違っても構築事例などから「実際に運営しているところ」に対して試すとアタック*1になるのでやめておきたいところです。
私は、以前に構築していた環境(1.3.4)と、最新のソースの2種類で実験をしています。


ユーザログインのところに多くあるのですが。「パスワードを忘れちゃったよテヘ」なあわてんぼうさんのために、いわゆるパスワードリマインダという機能がありまして、それは無論このEC-CUBEにも存在をいたします。
いくつか作りには種類があるのですが。尤もポピュラーなのは「emailアドレスを入れるとそのemailに対してパスワードを返信」してくれます。
ちなみに今回の範疇からは外れるので簡単なmemoにとどめますが。返信されるパスワードが「新しいモノ」である場合の方が、その業者を安心しやすいです。というか「あなたのパスワードはXXでした」なんて返してくるところは、酷いとパスワードを「DBの中に平文でそのまま」持ってたりするので怖いです。ちなみにEC-CUBEは前者。


おいといて。


さて。実際にemailを入れてみましょう。
ここで、おおよそ2種類の挙動に種類分けをする事が出来ます。
一つは「何を入力しようとも出力が全く同一である」パターンと。
もう一つは、例えば入力ミスなどの場合に、親切に教えてくれるパターンとがあります。
EC-CUBEは後者に属します。最新のソースで確認をしてみましょう。
eccube-2.1.2a/data/class/pages/forgot/LC_Page_Forgot.php
というプログラムを眺めています。
簡単に書きますと。まず

            $sql = "SELECT * FROM dtb_customer WHERE (email = ? OR email_mobile = ?) AND status = 2 AND del_flg = 0";

というSQLによって、emailの存在確認が行われています。
また。本会員としての登録がない場合に

                $sql = "SELECT customer_id FROM dtb_customer WHERE (email = ? OR email_mobile = ?) AND status = 1 AND del_flg = 0";	//仮登録中の確認

という処理も行われています。
結果として

$this->errmsg = "ご入力のemailアドレスは現在仮登録中です。
登録の際にお送りしたメールのURLにアクセスし、
本会員登録をお願いします。";
$this->errmsg = "ご入力のemailアドレスは登録されていません";

といったエラーメッセージが出力される可能性があります。
もうちょっとほかにも処理はありますが省略。


いわゆる「ユーザビリティ」として考えた場合に、これはそれなりに便利です。
というのも、emailを手打ちする以上、一定確率でのミスの可能性があります。それに対して「登録されていないよう」と教えてくれるのは、これはなるほどユーザビリティです。
さて問題です。この「ユーザビリティ向上」によって、どのようなメリットが誰に対して付与されるのでしょうか。


暗転。
では。ちと角度を変えて眺めてみましょう。
どうやらこれらの処理は、POSTメソッドで「mode=mail_check」+emailに適当なパラメタ、で動くようです。
えとですねぇもの凄く斜めな、これだけでは如何ともしがたいであろうイメージだけを記述します。

function emailアドレスっぽい文字列を次々に作成する関数();

/* -- */
while(1) {
  $uri_post_param['mode'] = 'mail_check';
  $uri_post_param['email'] = emailアドレスっぽい文字列を次々に作成する関数();
  $ret_html = POSTで適当なURIに対してHTTPして返り値をとる関数($uri, $uri_post_param);
  if ($ret_html =~ /ご入力のemailアドレスは登録されていません/) { continue; }
  if ($ret_html =~ /ご入力のemailアドレスは現在仮登録中です/) { $仮登録メールアドレス群[] = $uri_post_param['email']; continue; }
  // else
  $生きてるってかここの会員さんのメールアドレス群[] = $uri_post_param['email'];
}

ドキドキですねぇ。
いやまぁこのままじゃどうにもならんのですがね。もうちょっと小細工したり以下検閲削除。


明転。
なにやら真っ黒い会話が一瞬行われましたが。
はい結論を書きましょう「該当サイトの全会員のメールアドレスを、その気になれば抜き出せる」が今回の正解になります。より正しくは「メールアドレスの一斉取得をクラッカーに対して提供している機能である」と言えます。


さて。なにやらナチュラルに危険な発言書いてますが。どのようにヘッジをしたらよいのでしょうか。


入り組んだ処理やらなにやらはとりあえず置いておくとしてですな。
まずは「テンプレート修正」で速やかに逃げ切りましょう。

いち。余計な文言の出力原因である「」という文字列を徹底的に駆除/削除します。

に。一応ユーザビリティを考慮してこういった類の文言を付与するとよいです。「なお、メールがn分たっても届かない場合、メールアドレスの入力ミスが考えられます。n分たってメールが届かなければ、もう一度メールアドレスを入力してみてください」。
とりあえずこれで最低限防御できます。あとは、EC-CUBEさんがそのうち何とかしてくださるであろう事を待ちましょう。


セキュリティでは。こういったものを「不必要情報」と言います。
情報は、確かに多くの場合にユーザビリティを向上させますが。それは時として「クラッカーに対してより一層のユーザビリティを」与える結果になります。
技術者たるもの。常に「アタックの目線」を忘れずにものを作らなくてはいけません。


…って書くとEC-CUBEさんがけちょんけちょんなので、少しだけフォローをw
この話は、事前にmailでのやりとりで許可を頂いてます。で、そのときの彼らの態度なのですが、少なくとも公表その他に対して大変に紳士的でした。
うんまぁ正直、クラスの切り方ディレクトリの散らかりっぷりDB&SQLの駄目っぷり今回の件のようなセキュリティその他、正直なところあまり評価をしているソフトではないのですが。
少なくとも、その真摯な態度は評価に値するのではないかと思います。っつか「隠せばばれないよねぇ」セキュリティをしないだけ、そこらの凡百の以下略よりは遙かにましなのではなかろうかと思うわけです。


…いやしかしなんですなこの手の記事、バランスが難しい orz
突っ込みその他有りましたら歓迎いたしますので是非お願いいたします。

*1:これが不正アクセス禁止法に引っかかるかというと多分ひっかかりませんが、多分業務威力妨害とかそういう方向では有罪になるのではないかと思われ。詳細は法律家ではないので不明