ぽかぽかコード日和

とっても暑い夏の日にプログラミングはじめました☀️

【Security】セッション管理の不備+Laravel実装

概要

Webシステムでは、
CookieやセッションIDを使いアクセスしてきたユーザーがログイン済みかどうかを判定している。

攻撃者にCookieの中身やセッションIDを知られてしまうと、
ユーザーIDやパスワードを知らなくてもログイン済みのユーザーとして、
許可されている操作を不正に実行される攻撃。


  • セッション管理の不備を狙う攻撃手法は2種類ある。

    • セッションハイジャック
      利用者のセッションIDを推測・盗用によって不正に取得する。

    • セッションIDの固定化(Session Fixation)
      攻撃者が事前に用意したセッションIDをユーザーに使わせ、 ユーザーがログインした後、そのセッションIDを使ってなりすます。


発生しうる脅威

攻撃が成功した場合は、
攻撃者はユーザーになりすまし、ユーザーに許可されている操作を不正に実行できる。

  • 個人情報の漏洩

  • 金銭的被害
    不正送金やクレジットカードの不正利用、ECサイトで意図しない商品購入など

  • 登録情報の漏洩・改ざん
    アカウント情報など各種設定の変更や退会処理、掲示板への不適切な書き込みなど

原因

セッションIDの管理の不備

  • セッションIDの生成方法が単純(推測)
  • 通信を暗号化していない(盗聴)
  • ログイン後、新しいセッションで管理していない(固定化)

対策

根本的対策

1.推測困難なセッションIDを生成する(推測)
  • セッションIDを連番や時刻情報など単純なアルゴリズムで生成すると、推測や総当たり攻撃(ブルートフォース)で簡単に予測されてしまう。
  • 暗号論的疑似乱数生成機などを使って、長くランダムなセッションIDを生成する。
2.セッションIDをURLパラメータに格納しない(盗聴)
  • ユーザーが他のサイトに遷移したとき、Referer送信機能によりセッションIDの含まれたURLが送信されてしまい、攻撃者にURLを入手されると悪用される。
  • セッションI Dは、Cookie もしくはPOSTメソッドのhiddenパラメータに格納して受け渡しをする。
3.HTTPS通信でのCookieには必ずsecure属性を付与する。(盗聴)
  • secure属性によりHTTPS通信でのみ送信されるようになる。
4.ログイン後に新しいセッションIDを発行する(固定化)
  • ログイン後に新しいセッションを発行し、古いセッションIDは無効化する。
5.ログイン成功後に、秘密情報を作成して確認する(盗用)
  • ログイン成功したときに秘密情報を生成し、Cookieに格納する。
  • サーバー側に保持している秘密情報とCookieの秘密情報が一致することをリクエストごとに確認する。

保険的対策

6.セッションIDを固定値にしない(固定化)
  • セッションIDはユーザーのログインごとに新しく発行する。
7.Cookie有効期限を設定する(盗聴・固定化)
  • セッションIDを含むCookieの有効期限は必要最小限の期間に設定する。
  • 有効期限の設定(expires属性)を省略することで、ブラウザを閉じると自動的にセッションは破棄される。

Laravelでの実装例

1.設定ファイルでsecure属性を付与する

セッションを設定するconfig/session.phpファイルで

return [
 'secure' => env('SESSION_SECURE_COOKIE', true), //secure属性付与

 'http_only' => true,                 // JavaScript経由ではアクセス不可
 'lifetime' => 120,                   // Cookie(Session)の有効期限(分)
 'expire_on_close' => true,              // ブラウザ終了で破棄
];

☀︎env関数でsecureを設定する。

  • 第2引数はデフォルト値で.envファイルがない場合に適用される。

.envファイルで

SESSION_SECURE_COOKIE=true

☀︎secure は true となる。

2.デフォルトでセッション管理機能が搭載

  • セッションIDをURLパラメータに格納せずCookieで管理する。
  • 推測困難なセッションIDを自動で生成する。

3.標準認証機能のAuthを使ってログインする

  • ログイン成功したときに自動的にセッションIDが再生成される。
if (Auth::attempt($credentials)) {
    $request->session()->regenerate(); // セッションを再生成

    return redirect()->intended('dashboard'); //マイページへ
}
  • ログアウトのときは自動的にセッションが破棄される。
Auth::logout();

$request->session()->invalidate(); // セッションを無効化

$request->session()->regenerateToken(); // CSRFトークンを再生成

return redirect('/'); //トップページへ

参考にしたサイト