【メモ】httpとhttpsの混在環境でクッキーを利用する


httpとhttpsの混在環境におけるクッキーの問題点

先ずhttps対応された次のログインページにログインする。

https://あああ.net/login.php

ログインするとセッションIDをクッキーにセキュア属性付きで保存してクライアントに渡す。
セキュア属性付きのクッキーはhttpsでのみ送受信可能な為、盗聴の危険は無い。

session_id = "1351321";

次に下記のhttpsではないマイページに飛ぶものとする。

http://あああ.net/mypage.php

先ほどのクッキーに保存されたセッションIDはセキュア属性が付いている為httpsでしか見れない。よってmypage.phpではセッションが続かず、ログインページへのリダイレクトを余儀なくされてしまう。

これでは困るだろうという話。

前準備:セキュア属性を付けずにセッションIDをクッキーに保存する

httpでもセッションを継続させたいならセキュア属性を付けずにセッションIDをクッキーに保存する必要がある。

先ほどと同様に

https://あああ.net/login.php

にログインし、今度はセキュア属性を付けずにクッキーにセッションIDを保存する。

session_id = "1351321";

「セキュア属性=暗号化ではない」事を一応捕捉しておく。ログインページはhttpsなのでこのクッキーは暗号化されてクライアントに送信される。よって今回セキュア属性を付けずに送信したが、この段階では盗聴はできない(ここがとても重要)

次に下記のhttpsではないマイページに飛ぶ。

http://あああ.net/mypage.php

クッキーに保存されたセッションIDは今回はセキュア属性が付いていないのでhttpでも送信される。

問題はhttpでは暗号化が行われない為、この送信時に初めて平文でセッションIDがネット上に流れる事になる。

セッションIDがクッキーに入っており、対応するセッションがサーバー上で展開されていれば本人であるとしていた場合、セッションIDが盗聴されれば本人に成りすます事が出来る。

この状態だと、パスワードやクレジットカード番号等を確認できるページを用意していた場合漏洩してしまうので、対策が必要になる。

対策1:単純にログインページを設ける

パスワードやクレジットカード番号等の漏洩すると危険なページでは再度のログインを求めるようにしておく。
セッションIDからパスワードまでは判らないのでセキュリティを求められるものは全て再ログインを求めるようにしておけばとりあえずは防げる。

対策2:再ログインをさせたくない場合https時にセッションIDの他にトークンを送信する

この方法では先ずログイン時に適当なトークンを発行し、それをクッキーに保存する。
先ほどの流れに捕捉しながら解説する。先ずhttps対応された次のログインページにログインする。

https://あああ.net/login.php

ログイン後セッションIDをクッキーに保存する。セッションIDに対してセキュア属性は付加する必要は無い。

session_id = "1351321"; #セキュア属性なし

これ以外に更に適当なトークンを保存させる。このトークンにはセキュア属性を付加する。

session_id = "1351321"; #セキュア属性なし
token = "6846516"; #セキュア属性有り

セキュア属性に関わらず上記のクッキーはhttpsのログインページからは暗号化して送信される。よってこの段階では盗聴されることはない。
次に下記のhttpsではないマイページに飛ぶ。

http://あああ.net/mypage.php

クッキーに保存されたセッションIDはセキュア属性が付いていないのでhttpでも送信される。しかしトークンはセキュア属性が付いている為送信されない。

よってこの段階ではセッションIDは盗聴可能だがトークンは盗聴する事が出来ない。

ここでクレジット番号を確認する次のページにアクセスする。

https://あああ.net/credit.php

マイページと同様クッキーをサーバーに送信する。このページはhttpsな為セキュア属性のついているトークンも同時に送信される。

サーバー側(もといcredit.php)では送信されたトークンとセッションIDを確認し、セッションIDに対応するセッション変数に、送信されたトークンが格納されていたら認証できたものとする。

例えば盗聴者がセッションIDを盗聴できたので早速クッキーに設定し、意気揚々とcredit.phpにアクセスする。
しかし盗聴者のクッキーにはトークンが設定されていないのでこれでは認証できない。仕方ないので盗聴者はトークンも盗聴しようとするのだが、上述の通りトークンはhttpsプロトコルでしかやりとりされないので盗聴できない。

これによって成りすましを防ぐのがトークンを用いた方法となる。

どっちが良いんだろ

無駄な気がするけど両方共やった方が良いんじゃないかなぁとか思ったり思わなかったり・・・