ブログが続かないわけ

この日記のはてなブックマーク数
Webエンジニアが思うこと by junichiro on Facebook

ログイン処理が簡単と言い切れるか 〜 フィッシング対策も忘れずに

このエントリーを含むはてなブックマーク hateb
ログイン処理なんてほとんどのWebアプリケーションに必要だから、プログラマであれば簡単に作れると思われるかもしれないが、これが意外とあなどれない。初心者プログラマがやりがちな失敗から、最終的にどうあればいいのかを順を追ってみていこうと思う。

■1. (レベル0) セッション管理しない


これはどういうことかというと、もうほとんどネタのレベルなんだけど、IDとパスワードで認証しているにもかかわらず、中ページのURIに直接アクセスすれば誰でもアクセスできてしまう状態のことだ。今ではありえないことかもしれないけど、僕が業界に入った2000年頃はこんなサイトがたくさんあったんだ。

■2. (レベル1) ログイン後の画面を固定化


次のステップに進むと、こんな実装になる。ログインフォームを用意して、そこで入力されたID/Pass をget やpost でログイン後の最初のページ(以下、サービスTOP)に渡す方法だ。この場合、サービスTOPでID/Pass のチェックを行い、問題があればエラーメッセージを表示し、問題なければそのままサービスTOPの画面を表示するという流れになる。特に何か指示されない限り、このタイプのログインを作ってしまう人は多いんじゃないだろうか。この方法には3つ程問題点があると、僕は考えている。

1. サービスTOP がID/Pass のチェックを行うのは役割的におかしい。
サービスTOPはあくまでもコンテンツ(またはサービス)を提供することが目的のリソースなのに、そこでID/Pass の妥当性をチェックするというのは違和感がある。ログイン関連はそれだけで、ひとつのController にまとめるべきだ。

もし、「ログインはOpen ID にも対応させよう!」なんてことになったとき、サービスTOPのソースを修正しなければならないなんておかしいでしょ?

2. ログインすると常にサービスTOPの画面になってしまう。
サービスTOPもその他のサービス中ページも、リソースという意味では同等で、ユーザーは各サービス中ページにも直接アクセスしたいかもしれない。もちろん、セッションを保持していないユーザーが直接アクセスすると、セッションエラーとなり、おそらくログイン画面に遷移することになるだろう。しかし、そこでID/Pass を入力しても、その後の遷移先はサービスTOPとなってしまい、ユーザーが直接見ようと思っていたコンテンツではなくなってしまう。また、そのページまでたどらなければならないのは気分がよろしくないだろう。

3. エラーメッセージを表示するだけの画面
この方法だと、サービスTOPのコントローラで処理しているため、ID/Pass が間違っていた場合も再度ログイン画面を表示することが難しくなってしまう。そのため、「IDまたはPassが違います」というようなものだけを表示するエラー画面を表示することになってしまい、ユーザーはわざわざ戻るボタンで戻らないといけなくなってしまう。これは面倒だ。
(もちろん、これだけなら、エラーの場合にリダイレクトしたり、Viewを切り替えたりすることで、対応は可能だが。)

4. http とhttps の混在環境で機能しない
ログインだけhttps で、後はhttp にするというのはよくある話だ。この方法だとログインをhttpsにした場合に、httpに戻すタイミングが無い。

■3. (レベル2) 遷移先のURLをフレキシブルにできるログイン


これは、/login でログイン画面を開くとしたら、ログインチェックのpost(またはget)先も/login にするという方法だ。そして、ログインがうまくいった場合には、html のreflesh を利用して、ログイン後のページにリダイレクトさせる。

この方法だとレベル1の問題点はほとんど解決されている。
1. ログイン処理が独立したコントローラにまとめられる。
2. ログイン後のページを自由に制御できる。
ログイン画面を表示する際に、遷移先のURLを引数として受取ることで、そのURLをリダイレクト先にセットすることで、ログイン後のページを自由に制御することができる。

/login?url=http://www.example.com/contents/A
こんな感じでログイン画面に遷移先のURLを引数として渡す。ログインチェックに成功したときに、このurl の値をreflesh 先にセットしてリダイレクトさせればよい。この例ではログイン後にhttp://www.example.com/contents/A に遷移させることができる。

3. エラーの場合、エラーメッセージとともに最初の入力画面を表示することができる。
4. リダイレクト のタイミングでhttps からhttp に切り替えることができる。

このレベル2はほぼ完成型と言えるだろう。ただこの方法は油断するとフィッシングの温床になりかねない。
ログイン画面を表示する際に受取るURLに対して、なんのチェックも行わずにReflesh でリダイレクトさせると、これがフィッシングの格好の餌食になってしまう。このURLに適当なものをセットされて、ログイン後にそのURLに飛ばれたところで、何ら問題がないように思える。ところがここに落とし穴があるのだ。

フィッシングの方法については参考として、最後に説明する。

■4. (レベル3) 遷移先のURLをフレキシブルにできるログイン(URLチェク付き)

よって、レベル3(完成型)はレベル2と同じフローに、URLのチェックを加えたものだ。URLのチェックはホワイトリスト方式がもっとも安全だが、サイト内のコンテンツが増えるたびに、リストを更新していくのが面倒なので、ドメインを正規表現等でチェックする方法がいいだろう。

■参考 フィッシングのやり方

では、レベル2(つまり、URLのチェックが無い場合)のフィッシングの方法を確認しよう。今回の例では、ユーザーのIDとパスワードを盗むためのフィッシングサイトを作るということにする。

1. レベル2で実装されているサイトを見つける。
これのログインフォームのURLを http://www.example.com/login とする。
2. このログイン画面で適当にログイン失敗して、エラーの画面を表示させる。
3. そのエラー画面とまったく同じhtmlを作成する。
4. フィッシング用のサーバにこれを設置する。
このフィッシング用に設置した画面のURLを http://www.phishing.com/login とする。
5. http://www.example.com/login?url=http://www.phising.com/login というURLを踏ませる。
これを踏ませる方法は、Spamでもmixi に書込むでもどんな方法でも構わない。
6. 踏んだ人は本物のexample.com のログイン画面にアクセスすることになる。
7. そこでID/Pass を入力するとエラー画面に遷移する。
本当は認証がうまく行っているのだが、ログイン完了後にhttp://www.phising.com/login に遷移しているため、エラー画面が表示されるのだ。もちろん、これは既にフィッシング側のサーバにアクセスしている状態なので、URLに注意をすれば引っかかることはないが、気づかないこともある。
(アドレスバーを隠すタイプであれば、より確実性はあがる)
8. 「あれ、入力ミスったかな?」なんて思って、もう一度ID/Passを入力してしまう。
これはもうフィッシング用のサーバなのに!
9. これでフィッシング用のサーバで簡単に正規のID/Passを頂くことができてしまう。
しかもこの後、巧妙に正規のログイン完了後の画面に遷移させられると、フィッシングにあったことに気がつかない可能性すらある。

フィッシングは本来ユーザーが注意すべきものだと思うけれど、システム開発側でも被害を起こりにくくすることはできる。

【2008/08/21 追記】ごめんなさい。参考にしたサイトを掲載するのを忘れていました。
フィッシングについてはほとんどこちらを参考にした。
ログイン成功時のリダイレクト先として任意サイトの指定が可能であってはいけない

参考URLをご覧頂ければわかるように、はてなでさえほんの1年くらい前はこの対策がなされていなかった。しかし、だから初心者が知らなくてよいということではない。1年前はそうでも、今ではプロであれば常識として欲しいことだから。

しかし、こういうことはWebアプリ開発の入門書にはなかなか書いていない。

ユーザー企業から直接RFPが出てくる場合、たかがログイン周りでここまで細かく指示されることはない。しかし、プロの開発者であればここまで想定して実装してほしいと思う。

今まで外部の人に仕事をお願いしてきて、いきなり完成型で実装して頂いたことは、残念ながら一度もない。

この記事のトラックバックURL
http://en.yummy.stripper.jp/trackback/987602
トラックバック
2008/08/21 (木) フィッシング エロゲ twitter
きょうは twitter に 18 件。 はてブに 2 件。...
| ヒラメキつぶやきコレクション | 2008/08/22 8:31 AM |
ログイン認証が必要なサイトの構築
サーバに保存するユーザ情報 name識別子(ユーザ名)cryptedPassword暗号化したパスワードsalt暗号化に使うキー パスワードは素のまま保存しない サーバがクラックされてユーザ情報が盗まれても大丈夫なようにするには 素のパスワードをMD5やSHA1でハッシュ化した値を保
| assari (PukiWiki/TrackBack 0.3) | 2008/08/24 12:06 AM |
コメント









関連情報