Webセキュリティの小部屋

Twitter のフォローはこちらから Facebook ページはこちら Google+ページはこちら RSSフィードのご登録はこちらから
公開日:2015年2月22日
最終更新日:2015年3月14日

僕が考える最強の自動ログイン方法

Web アプリケーションの自動ログイン方法をネットで調べてみると、内容が不完全だったりセキュリティ上問題のある情報しか見つかりません。自動ログインは一般的であるにも関わらず、議論の土台すらネット上で示されていないのは問題だと感じます。

という訳で、タイトルは釣りですが、自動ログイン処理をどのように行えばよいか真面目に考察し、PHP での実装例を示してみます。

本当は、セキュリティでガチガチに固めたい場合は、自動ログインは実装しない方が安全なのですが、自動ログインそのものに対する課題は前提にあるとし、その課題を解消する方向で考えていきます。

まずは、自動ログインの定義を明確にしましょう。

「自動ログイン」とは、一度ログインしたら「ユーザーの選択」により、2回目以降のログインを省略できる機能のこととします。この機能が目的とするのは、ログインというユーザーの負担を省略することにより、ユーザーの負担を減少させ、ユーザー体験を向上させることです。

ここで「ユーザーの選択」を強調していることに注意してください。自動ログインはセキュリティレベルを下げる可能性があるため、あくまでオプションとして提供し、採用自体はユーザーに任せています。

また、自動ログインは、利便性とセキュリティの確保のため、以下の機能を持つものとします。

1.複数ブラウザ、複数パソコンで個別に管理される
2.想定されるセキュリティの脆弱性に対処する

1については、1つのブラウザやパソコンではログアウトして自動ログインを無効にするけれども、他の環境では自動ログインを継続するようなケースを想定しています。例えば、会社のパソコンではログアウトするけれども、自宅のパソコンでは自動ログインを有効にしておきたいようなケースです。

2がこの記事の主題です。ここをなんとかしないと最強の自動ログインは実現できません。

まず、大前提として自動ログインでは、以下の2点が担保されていなければ安全とは言えません。

・HTTPS による通信を行う
・ログイン画面から HTTPS にする

ログイン画面から HTTPS にするのは、ログイン画面が改ざんされていないことを保証するためです。ユーザーに安心感を与えることにもなるので、必須の対応です。

また、自動ログインを実現するためには、Cookie を利用することが必須です。しかし、Cookie に以下の情報を格納して自動ログインを実現することは NG です。暗号化しようがハッシュ化しようが NG なものは NG です。

・ユーザーID
・パスワード

これは、Cookie の性質として、Cookie の内容は人間が簡単に見ることができるし、クロスサイトスクリプティングの脆弱性によって攻撃者に盗まれる可能性があるためです。攻撃者の手に渡れば、これらの情報は簡単に悪用されてしまいます。

別の自動ログインの実現方法として、セッションの有効期間を2週間などの長期間にするとの方法も考えられますが、この場合、2つの問題が起こりえます。

1つ目は、サーバーリソースの問題です。自動ログインを必要としないユーザーを含めた多数のユーザーがログイン状態になって、サーバーのメモリを圧迫します。

2つ目の方が問題なのですが、長期間セッション状態を維持するということは、セッション ID を固定化するということでもあります。

これにより起こりうるリスクは、セッション ID の漏洩によってセッションハイジャック(のっとり)の被害を受けることです。セッション ID が長期間固定化されればされるほど、このリスクは高まります。

では、どうすればよいのか?

それは、一時的なトークンを用いて自動ログインを実現することです。

具体的には、一度目のログイン時に暗号論的擬似乱数生成器による乱数を生成し、それをトークンとして Cookie とサーバー側で保持します。そして、2回目以降のアクセスで、Cookie とサーバーのトークンを比較することで自動ログインを実現します。

この時、注意しなければいけないのは、トークンは「一時的」なものにする必要があるということです。トークンを固定にすると、セッション ID を長期間同じにすることと同じ問題、つまりセッションハイジャック(のっとり)のリスクが高まります。

この問題に対応するために、自動ログインでは、自動ログインが成功する度に、トークンの振り直しを行います。また、古いトークンは忘れずに削除します。

さらに安全にするために、Cookie のトークンでは、HttpOnly 属性と secure 属性を有効にします。

HttpOnly 属性を有効にすることにより、JavaScript から Cookie にアクセスできなくなり、クロスサイトスクリプティングの脆弱性による影響を緩和できます。secure 属性をつけることにより、HTTPS での通信でのみ Cookie の値をサーバーに送信するようになります。

これが自動ログインを安全に行うための対策です。

前置きが長くなりましたが、PHP で実装してみましょう。

環境は、PHP + MDB2 + MySQL になります。

処理は以下の図のようになります。

Pic01

テーブルは以下のようになります。ここでは、USER_ID は固定で不変のものとします。また、AUTO_LOGIN テーブルの ID はオートインクリメントの数値です。

・USERS テーブル

  • USER_ID
  • PASSWORD

・AUTO_LOGIN テーブル

  • ID
  • USER_ID
  • TOKEN
  • REGISTRATED_TIME
なお、今回は自動ログインの解説のため、ログイン処理を簡略化しています。ログイン処理の安全な実装には、salt とストレッチングを組み合わせたパスワード管理が必要です。パスワード管理については以下の記事を参照してください。
 
■ログイン画面(login.php)
 
ログイン画面のポイントは、Cookie にトークンが設定されていれば、自動的にログイン処理にリダイレクトすることです。

■ログイン処理(logincheck.php)

ログイン処理には、自動ログインのキモなので重要な部分が多いのですが、いくつかポイントを説明します。

まず、トークンの生成ですが、openssl_random_pseudo_bytes (>=PHP5.3.0) とう関数を利用しています。この関数は、PHP で暗号論的擬似乱数生成器を用いた乱数を生成できます。また、乱数の桁数は 32 桁にしています。セッション ID と同等の強度です。

トークンは、サーバー側も Cookie も 2週間の期限をつけてあります。サーバーとクライアントの双方で期限を設けることにより、安全性が増すことを期待しています。

また、ログインが失敗した場合は、トークンの削除(サーバー側・Cookie)をしています。成功した場合も古いトークンを削除します。トークンは自動ログインの度に新規作成しますが、古いトークンが悪用されないようにするためです。

■Welcome 画面 (welcome.php)

Welcome 画面には、ログアウト機能をつけてあります。自動ログインは重要ですが、場合によりログアウトが必要になるためです。

実際の実装では、強制ブラウズなどの対策も必要になってくるでしょう。

■ログアウト処理(logout.php)

ログアウト処理には、特筆すべき点はありません。サーバー側と Cookie のトークンを削除しているだけです。

おわりに

自動ログイン処理の内容と PHP での実装を見てきましたが、いかがだったでしょうか。

簡単に思える自動ログインですが、いざ実装するとなると考慮することが多く、意外に長いコードになっているかと思います。

ですが、自動ログイン処理では、この程度の考慮は必要です。

ユーザーの利便性のためとはいえ、セキュリティレベルを下げる実装では、相応の対応が必要ということですね。

この記事が自動ログインの議論のきっかけになれば幸いです。

追記:クロスサイト・リクエストフォージェリ(CSRF)対策について

自動ログインを導入する際に、懸念されるであろう「クロスサイト・リクエストフォージェリ(CSRF)」の対策についても触れておきます。

結論から言うと、通常の CSRF 対策ができていれば、自動ログインを導入しても CSRF の脆弱性は発生しません。

一般的な CSRF の対策では、サーバー側で乱数で生成したトークンをブラウザに送信し、ブラウザは POST リクエストでトークンをサーバーに再送信することで、サーバー側で正しいリクエストかどうか判断します。

CSRF の詳しい内容は、以下の記事を参考にしてください。

では、自動ログインはどのようになるでしょうか。

仮に悪意あるサイトでリンクをクリックさせ、自動ログインのサイトにユーザーをアクセスさせようとしても、CSRF 対策がされているサイトでは、そもそも CSRF のトークンがないとリクエストは拒絶されてしまいます。

また、自動ログインで、サイトを表示するときにログイン画面にリダイレクトさせて認証を行うようにすれば、不正なリクエストを取り除けるのでなお安全です。

注意するとすれば、自動ログイン処理後に表示される画面で、重要な処理を自動実行されないような実装にしておく必要があるところでしょうか。

また、CSRF 対策の1つである、「重要な処理の実行時にパスワードの入力を求める」を実装しておけば、さらに安全です。Amazon のサイトでは、このような方法を採用していますね。

このように、自動ログインでは、CSRF の対策を正しく実装しておけば、CSRF の問題は発生しません。CSRF 対策の方が大変な気もしますが、自動ログインは正しい方法で実装すれば安全ということができるでしょう。


スポンサーリンク




カテゴリー:ブログ

Twitter でも、いろんな情報を発信しています。



コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA