$_SESSION

$_SESSION(セッション変数)

$_SESSION は、定義済み変数のひとつであり、ページ遷移後やリロード後も値を保持し続けることができる変数です。

ECサイトのように、複数ページで値を保持しておきたい場合などに使用します。

なお、$_SESSIONは、スーパーグローバル変数であり、プログラム全体のどのスコープでも呼び出せます。

関数の内部で呼び出す場合、グローバル変数はグローバル宣言しますが、スーパーグローバル変数は、グローバル宣言すら必要ありません。

セット方法

<?php
session_start();					// セッションを開始
$_SESSION[キーA] = '値';				// セッション変数をセット
$_SESSION[キーB] = array( '値A', '値B', '値C' );	// 配列をセットすることも可能
?>

呼び出し方法

<?php
session_start();	// セッションを再開
$_SESSION[キーA];	// セッション変数を呼び出す
$_SESSION[キーB][0];	// セッション変数にセットした配列の1つ目の値を呼び出す
$_SESSION[キーB][1];	// セッション変数にセットした配列の2つ目の値を呼び出す
$_SESSION[キーB][2];	// セッション変数にセットした配列の3つ目の値を呼び出す
?>

セッション管理の問題

PHPのセッション管理は、セッションの固定化(Session Fixation)問題というものがあります。

この問題に対応するために、ログイン後にセッションIDを作り直して、ログイン後のセッションを保護するという対策が必要です。

なお、このセッションの固定化を原因としたセッションハイジャックを防ぐために、セッションIDを置き換える関数「session_regenerate_id」がPHPには用意されています。

session_regenerate_id() を使うとセッションIDは新しいものと置き換わりますが、セッション情報は維持されるという特徴があります。

ログイン後にのみ重要なデータを参照て処理する場合、ログイン後に session_regenerate_id() でセッションIDを作り直せばログイン後のセッションは保護されるのでセキュリティ上の問題はほぼ発生しません。

しかし、使い方や挙動などで注意すべき点がいくつかあるため注意が必要です。

セッション攻撃方法(セッションハイジャック)

ログインが必要なサイトのURLが次のURLだとします。

http://example.com/login/

攻撃者はURLにセッションIDを記述したURLリンクを作成します。

http://example.com/login/?PHPSESSID=abcdefg

攻撃対象者がこのリンクをクリックするとセッションIDがabcdefgに設定されているので攻撃者はこのセッションIDを利用してサイトにアクセスできるようになってしまいます。

セッション攻撃への対策(セッションIDの再生成)

セッションIDの再生成 サンプル(PHP 5.1.0 以降)

PHP 5.1 からは第1引数が追加されました。引数にtrueをセットすることで、古いセッションIDは破棄されて毎回新しいIDが振られます。

session_start();
session_regenerate_id(TRUE);

セッションIDの再生成 サンプル(PHP 5.1.0 まで)

PHP 5.1.0 までは、古いセッション情報が削除されずにそのまま残ってしまいます。

そのため、PHP5.1.0 までの場合は、古いセッション情報を明示的に削除する必要があります。

session_start();
$old_id = session_id();
session_regenerate_id();
unlink(session_save_path() . 'sess_' . $old_id);

セッションIDの再生成による問題

session_regenerate_id() を使うと、毎回セッションIDが変わるため通信エラーが起こった際にセッションが切れてしまう可能性があります。

対策としては、SSLを利用してログイン時のみ書き換える仕様にするのがいいのかもしれません。

携帯電話への対応

携帯電話からPHPのセッションを機能を使う場合、端末によってはクッキーが利用できない場合があるため、そのままでは使うことができません。

下記の設定が有効になると、リンクの後ろに自動でセッションIDが付加され、セッション変数が引き継げるようになります。

※ただしクッキーが使える端末で、「session.use_cookies On」の場合には、セッションの管理にはクッキーが優先して利用され、URLにセッションIDはつきません。

セッションIDが付加された例:
<a href="index.php?PHPSESSID=b37b5e8e31118c45e19a5fb6b70c215a">トップへ</a>

なお、ページの移動に静的HTMLを挟んだり、引数をつけないでリダイレクトしたりすると、セッションは切れてしまいますので注意が必要です。

設定1:サーバ側の設定

セッションを使いたい場合は、インストール時のconfigureオプションに、「-enable-trans-sid」を付ける必要があります。

なお、Windowsの場合は特に設定の必要はありません。

設定2:php.ini で設定する場合

また、「php.ini」の設定で、次のように設定します。※設定変更後はWebサーバの再起動が必要です。

session.use_trans_sid = 1

なお、設定内容は、phpinfoで確認できます。

設定2:.htaccess で設定する場合

「.htaccess」でも設定することができます。※.htaccessでの設定上書きが許可されている場合のみ

php_flag session.use_trans_sid On

なお、設定内容は、phpinfoで確認できます。

設定2:PHP で対処する場合

PHPのコード内で、下記のコードでの設定できますが、その場合は「session_start();」より前に実行する必要があります。

ini_set('session.use_trans_sid', '1');

携帯電話向けのセッション攻撃への対策

上記設定のままですと、URLに固定のセッションキーがついたままの状態のため、リンク先のページにRefererが漏れてしまったり、メール等でURLを転送した場合などにセッションハイジャックされてしまう可能性があります。

そこで安全度を高めるために、次のような対応策を平行して行うと良いようです。

  1. クッキーを利用できる端末の場合は、クッキーを利用する
  2. 端末IDによる認証+IPアドレス制限を行う
  3. session_regenerate_id関数を利用する

1.クッキーを利用できる端末の場合は、クッキーを利用する

auとソフトバンクの最近の機種ではクッキーが利用できます。

クッキーが利用できれば、URLにセッションIDを付加しなくてすみますので、URLからの漏洩を防ぐことができます。

セッションの管理にクッキーを優先して利用するには、「php.ini」または「.htaccess」で、「session.use_cookies On」と設定されている必要があります。

2.端末IDによる認証+IPアドレス制限を行う

まず.htaccessなどで、携帯キャリアのIPアドレスからのみアクセス可能な状態にします。

その状態でセッションに端末IDを格納し、アクセスの度に認証チェックを行うことでなりすましを防ぎます。

IPアドレスの制限をかけるのは、Refererが漏れている場合は、端末IDも同時に漏れているケースが多いためです。

端末IDはリクエストを偽造することで、なりすまされる可能性があるため、携帯実機からのアクセスのみとすることで安全度を高めます。

3.session_regenerate_id 関数を利用する

「session_regenerate_id」は、アクセスの度にセッションIDを変更するためのものです。

PHPのバージョンによって対処法が異なりますので注意が必要です。

詳しくは下記を参照して下さい。

セッションIDの再生成 サンプル(PHP 5.1.0 以降)
session_start();
session_regenerate_id(TRUE);
セッションIDの再生成 サンプル(PHP 5.1.0 まで)
// セッション開始
session_start();

// 古いセッションを保存
$sess_tmp = $_SESSION;

// セッション変数を破棄
session_destroy();

// セッションIDを再生成
session_start();
session_regenerate_id();

// セッションを元に戻す
$_SESSION = $sess_tmp;

参考