【PHP セッションハイジャック対策】セッションIDを変更する



PHPではセッションハイジャックという攻撃方法があります。
攻撃防ぐ簡単な方法としてはセッションIDを切り替える方法で、対策を行えます。
今回はその対策方法のご紹介。

session_regenerate_idを使用

phpマニュアル:session_regenerate_id
session_regenerate_idを使用すると呼ばれる毎にセッションIDを新しく書き換えます。
これをアクセス毎に呼び出すようにするとセッションハイジャック対策になります。

session_regenerate_id使用サンプル
<?php
session_start();

$old_sessionid = session_id();

session_regenerate_id();

$new_sessionid = session_id();

echo "古いセッション: $old_sessionid<br />";
echo "新しいセッション: $new_sessionid<br />";

print_r($_SESSION);
?>

session_regenerate_idの問題点

セッションハイジャック対策でsession_regenerate_idを入れたのはいいが使用すると良くセッションが切れてしまうようになります。

session_regenerate_id(true)にすると旧セションデータを削除する設定になるのでセッションがより切れやすくなります。
下図はこの問題を簡単に表したものです。

同時にアクセスされた場合、同時にsession_regenerate_idが走ってしまい、セッションデータが上手く引き継げない場合があるようです。

session_regenerate_idの対策

対策自体は簡単です。
同一のタイミングでsession_regenerate_idの発動が起きないようにするだけ。
// 初期接続
if(!isset($_SESSION['expires'])){
    // 接続時間の保存
    $_SESSION['expires'] = time();
}

// 1秒以内に同時アクセスされた場合も消えるので確率を設定
if(mt_rand(1, 10) === 1) {
    // 最新のアクセスから1秒過ぎたらセッションIDを書き換え
    if ($_SESSION['expires'] + 1 < time()) {
        // 書き換え時間を再設定
        $_SESSION['expires'] = time();
        // セッションID切り替え
        session_regenerate_id(true);
    }
}
色々試してはみましたが、これでセッションが切れにくくなりました。
体感ですがsession_regenerate_idの前に有効時間を書き換えないとセッションが切れる確率が高かったです。


コメントを残す