ログイン認証無しの一般的なメールフォーム等の入力、確認、完了ページをセッションで管理する場合についてお聞きしたいので教えていただけないでしょうか。
セッションIDの保存にクッキーを使用しているのですが、
1 どのタイミングでセッションを再生成すればよいか。
現在は入力フォームに入った段階で、セッションスタート後すぐにsession_regenerate_idをしています。
その後、リロードした場合や確認ページから入力内容の編集で戻ってきた場合に指定秒経過ごとに再度session_regenerate_idをしています
2 セッションクッキーのタイムアウトについて
入力ページで決めうちでsession_set_cookie_paramsを使用し、expire属性に例えば3600(1時間)と設定するのが良いのか、もしくは、setcookieでページ遍移ごとに有効期限をリセットして延長する方法が良いのか、どちらが良いのか疑問です。
また、セッションクッキーには時間を設定せずに「 0(ゼロ) 」にした方がクッキーをクライアントのメモリのみに保存するので安全にも思います。
どうか、ご教授いただけないでしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
ご質問のテーマについては、以下の二種類の観点を持つことがよいと考えます。
(a)他に脆弱性がなくても単独で情報漏えい等が発生する脆弱性という観点
(b)他に(クロスサイトスクリプティングなどの)脆弱性がある場合に被害を緩和する観点
まず、(a)に関して言えば、ログインせずに、セッション変数で情報を持ち回りする場合、「ログイン前セッションIDの固定化攻撃」が成立する場合があります。
これは、セッションIDのクッキー(デフォルトではPHPSESSID)の値を外部の攻撃者にセットされた場合、そのセッションIDは攻撃者がわかっているので、セッション変数に値が入ったタイミングで攻撃者がサイトにアクセスすると、入力途中の値を攻撃者に閲覧される可能性がある、というものです。
それでは、セッションIDのクッキーを外部からセットする方法ですが、以下のようなものがあります。
- クッキーモンスターバグによる方法(地域型JPドメイン名、都道府県型JPドメイン名を使用していて、IE利用の場合)
- HTTPSを使用しているサイトで、通信路上に攻撃者がいる場合
クッキーモンスターバグとは、IEを利用していると、Set-Cookie時に domain=tokyo.jp など広範囲に適用されるクッキーが作れてしまう問題のことです。例えば、東京都のドメイン名は metro.tokyo.jp ですが、地方公共団体以外でも xxxx.tokyo.jp のドメイン名を持つサイトは非常に多いです。(Googleで site:tokyo.jp で検索してみてください)これらのサイト全てで、domain=tokyo.jpのクッキーを発行できる(ただしIEユーザのみ)ので、クッキーの汚染は現実的な問題になります。
HTTPSを利用している場合については下記の記事を参照ください。
HTTPSを使ったほうが危険になるのかと驚かれるかもしれませんが、そうではありません。HTTPSを使っておらず通信路上に攻撃者がいる場合は、クッキーの盗聴も改変も可能ですし、そもそも生の個人情報等も盗聴できるので、こちらは問題外ということになります。それを防ぐためのHTTPSであるわけですが、(クッキーの盗聴は防げるが)クッキーの改変は防げない、という問題です。
さて、ログイン前セッションIDの固定化攻撃を防ぐ確実な方法は、適切なタイミングでセッションIDを変更することです。そして、適切なタイミングを下記に示します。
- 秘密情報をセッション変数に格納する直前
このタイミングでセッションIDを変更すると、「攻撃者が知っているセッションID」には秘密情報は入らないので、確実な対策になります。
ログインを前提とするサイトの場合は、ログイン確認直後、かつセッション変数にログイン情報をセットする前にセッションIDを変更するべきですが、これも同じ理由です。
し・か・し・な・が・ら、ログインをしないケースでは、上記を実施しているウェブサイトはあまり多くないように見受けます。その理由は、セッションIDの固定化攻撃が成立する条件が厳しいわりに、攻撃により得られる「成果」があまり多くない(ログイン状態を乗っ取れるわけではない)ので、脆弱性を許容していると考えられます。(単に知らないだけという可能性ももちろんあります)。
一方、(b)に関しては、セッションタイムアウトの設定が有効です。こちらは、セッションのexpires指定による方法もありますが、より望ましい方法は、セッション変数として「最終クセス日時」を保存して、アクセスの度に確認することです。こうすれば、クッキーにはexpiresを指定しないため、クッキーがパソコンのファイルに保存されることもなくなります。
投稿2017/02/24 11:38
総合スコア11705
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/24 14:34
2017/02/24 14:39
2017/02/24 15:38
0
(2/24 ご質問の1への回答を若干編集しました)
(2/25 コメントを受けてセッション開始の条件を訂正)
まず、参考資料を示します。
- IPA セキュアプログラミング講座 (Webアプリケーション編)
第4章 セッション対策
これはひと通り読まれるとよいと思います。
要点はいろいろありますが、セッションIDを守ることに絞ると、次の3つにまとめられるようです。
- セッションIDの推測に対する対策
- セッションIDの奪取に対する対策
- セッションIDのお膳立てに対する対策
このうち1.と3.については、PHPのセッション管理機構を使っていれば通常は問題ないでしょう。
また2. については、cookieの使用は効果的です。ただしcookieを使うだけでは十分でなく、通信路の暗号化を必須とする (HTTPSにした上で、cookieにsecure属性をつける) ことや、スクリプトによるアクセスを防ぐ (httponly属性をつける) ことも検討するべきでしょう。
前置きおわり。
1 どのタイミングでセッションを再生成すればよいか。
session_regenerate_id()は、あまり必要ないと思います。
セッション開始時はsession_start()だけでいいです。実装上は、IDを生成するたびにOSの(疑似)乱数生成器を使っているだけなので、あらためてsession_regenerate_id()しても暗号論的な強度は変わりません。
また、セッションの生成と破棄ですが、次の原則を守るべきです。
- 守りたい通信が開始するときにセッションを開始する。
- 守りたい通信が終了したら即座にセッションを破棄する。
今回の場合は、入力フォームで最初に入力があった段階でセッションを開始し、送信完了 (または取り消し) 時にセッションを破棄するようにします。
なお、セッションの破棄のしかたについては末尾[1]に補足します。また、今回はログインはしないとのことですが、する場合について[2]に補足します。
次に、セッション中のセッションID再生成について考えます。
上記1. (セッションIDの推測) については、再生成しても特に乱数の強度が上がるとは思えません。また、2. (セッションIDの奪取) に対して効果はありません。対策は上で述べた通り、通信路を守るなどするしかありません。3. (セッションIDのお膳立て) に対しても特に効果はないです。
一方で、次のような場合は問題が発生します。
- フォームの送信ボタンの2度クリックをしてしまった場合。
- リンクの2度クリックをしてしまった場合。
- ページ中に埋め込まれたコンテンツ (画像など) も、セッション管理の対象である場合。
複数回のリクエストがほぼ同時に発行されるため、その間にセッションIDが再生成されると、クライアントが最新のセッションIDを受け取り損ね、セッションが切れてしまう可能性があります。
ですので、上で述べた対策がとられている限り、ログインセッション中にセッションIDを再生成する必要はないと思います。次で述べるセッションクッキーのタイムアウトが設けられていればいいでしょう。
2 セッションクッキーのタイムアウトについて
cookieのタイムアウトの長さは、作ろうとするシステムの仕様次第だと思います。ただし、絶対的なタイムアウトは設けるべきです。
再度アクセスしたときも継続して使いたい情報があるのなら、cookieにタイムアウトを明示的に設定すればいいと思います。そういうものがなければ、cookieにExpire属性やMax-Age属性を設定せず、ブラウザを閉じた時にcookieが消えるようにすればいいと思います。
ただし、cookieのタイムアウト設定はクライアントが正しく処理してくれることが前提なので、サーバ側では絶対的なタイムアウトを設けて、それを過ぎたセッション情報をサーバから消去すべきです。
絶対的なタイムアウトも、仕様に応じて数時間から数日までいろいろでしょう。
[1] セッション破棄のしかたはPHPのマニュアルにも例がありますが、説明を補足しておきます。
$_SESSION = array(); # セッションデータを消す。 $params = session_get_cookie_params(); # cookieを期限切れにして消す。 setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"] ); session_destroy(); # セッションを破棄する。
まずセッションデータを消しておかないと、セッションを破棄するまでの間にcookieを送り込まれる可能性があります。ですので、厳密にやるのなら上のようになります。
[2] ログインする場合について補足します。
上で述べた原則により、基本的にはログイン成功したときにsession_start()し、ログアウトしたらすぐにsession_destroy()するようにします。
なお、ログイン中以外でもセッションを使っているかもしれませんが、ログイン後に同じセッションを使いまわす (session_regenerate_id()でIDだけ変える) ようにしないほうがいいでしょう。ログインしていない間に攻撃者から情報を注入されたときに、それを信頼してログイン後にも使ってしまうようなコードを書けてしまいます。
投稿2017/02/23 06:01
編集2017/02/25 05:30総合スコア4443
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/02/23 15:05
2017/02/24 08:37 編集
2017/02/24 15:55 編集
2017/02/24 14:38
2017/02/24 20:56 編集
2017/02/25 05:41 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。