あなたのサイトは大丈夫? PHPでやるべきセッションハイジャック対策!

前回、Cookieとセッションについての基本的な部分をご説明させていただきました。

今回はもう一歩踏み込んで、PHPでセキュリティを高める為にすべき事をご説明したいと思います。
動くだけでなくセキュリティも意識したシステムとなるよう、しっかりと対策していきましょう。

セッションIDをURLに含めない

前回のブログで、PHPではCookieを利用してセッションIDを管理していると言いましたが、
設定によってはURLにセッションIDを付加して管理することも可能です。
デフォルト設定ではCookieで管理する設定になっていますので変更する必要はありませんが、
この設定を変更するとセッションIDが画面上に表示されている状態となります。
画面を見られただけでセッションIDが盗まれてしまい、
ユーザーのなりすましなどをされてしまう可能性があるので、
PHPでセッションIDをURLに含めないよう、php.iniを以下の設定となっているか確認しましょう。

; 0:透過的なセッションIDの付加をしない。
session.use_trans_sid=0

; 1:セッションIDの保存にcookieを使用する
session.use_cookies=1

; 1:セッションIDの保存にcookieのみを使用することを指定
session.use_only_cookies=1

セッション名を変える

セッションIDをサーバーとクライアント間でやり取りする際に、どのような名前でやりとりするか変更します。
デフォルトでは「PHPSESSID」となっていますので、
このままだと「PHPSESSID」がセッションIDのcookieだとすぐに特定されてしまいます。
セッション名を変更しておくことでセッションIDのcookieが特定されにくくなりますので、
デフォルト値からしっかりと変更しておきましょう。
例えば、セッション名を「hogehoge1234」に変えるには、php.iniに以下の様に設定します。

; セッションIDのキー値
session.name=hogehoge1234

下記の様にセッション名が「hogehoge1234」となっていることが分かります。
session_20160505_1

また、同一サーバーで複数のアプリケーションを立ち上げる場合など、
セッションを分けたい場合があるかと思います。
その場合、プログラム上でセッション名を指定することでセッションを分けることができます。
下記の様に、セッションをスタートする前にsession_name関数で指定します。

<?php
  session_name('abcd9999');
  session_start();
?>
<html>
<head><title>セッション</title></head>
<body>
<?php
    if (!isset($_SESSION["cnt"])){
        $_SESSION["cnt"]=1;
    }else{
        $_SESSION["cnt"]++;
    }
    print($_SESSION["cnt"].' 回目の訪問です。');
?>
</body>
</html>

上記の様にプログラムで設定してからセッションをスタートすると、
下記の様にcookieに保存されるセッション名がプログラム上で設定した値となります。
session_20160505_2

推測困難なセッションIDが生成されるようにする

デフォルトの設定でも、IPアドレスや現在時刻などから乱数を生成しますが、
完全に推測不可能では無く、アクセスが多いサイトではセッションIDが重複する可能性もあるようです。

より推測困難なセッションIDを生成するには、php.iniに以下の様に記載します。

; 乱数発生源とするファイル
session.entropy_file=/dev/urandom
; entropy_file から読み取るバイト数
session.entropy_length=32

なお、これによって生成されるセッションIDの桁数が増えるわけではありません。

HTTPS通信で利用するCookieにはsecure属性を付与する

HTTPS通信時のみCookieを送信するようsecure属性を設定します。
設定しない場合、HTTPS通信時のCookieがHTTP通信時にも見ることができてしまい、
セッションIDが盗聴される危険性があります。
ただし、ページによってHTTP環境とHTTPS環境が混在するなどの場合、
セッションを継続することができなくなってしまうので注意が必要です。
Cookieにはsecure属性を付与するには、php.iniに以下の様に設定します。

; 1:セキュアな接続を通じてのみCookieを送信する
session.cookie_secure=1

ユーザーが設定したセッションIDは受け付けない

PHPが初期化したセッションID以外のセッションIDは受け付けないようにします。
この値が0の場合、例えばユーザーが適当に生成した値がセッションIDとして扱われてしまいます。
これを回避するには、php.iniに以下の様に設定します。

; 1:初期化していないセッションIDを受け付けない
session.use_strict_mode = 1

セッションIDをアクセス毎に変更する

PHPのセッション管理にはSession Fixationという問題があります。
これを防ぐにはセッションIDをアクセス毎に変更する必要があり、
phpではセッションを継続しつつ、セッションIDを変更する関数が用意されています。
以下の様に、セッションスタート後に、session_regenerate_id関数を実行します。

<?php
  session_start();
  session_regenerate_id(true);
?>
<html>
<head><title>セッション</title></head>
<body>
<?php
    if (!isset($_SESSION["cnt"])){
        $_SESSION["cnt"]=1;
    }else{
        $_SESSION["cnt"]++;
    }
    print($_SESSION["cnt"].' 回目の訪問です。');
?>
</body>
</html>

上記のようにsession_regenerate_idを実行すると、
下記の様にセッションを維持したまま、セッションIDが変更されます。

1回目の通信
session_20160505_3

2回目の通信
session_20160505_4

まとめ

今回は、セッションに関わる部分について、セキュリティを高める方法をご紹介させていただきましたが、
環境や言語など状況によって必要なセキュリティ対策は異なります。
また、技術の進歩と共に必要な対策も変わっていきますので、
一つ一つしっかり対策をしていきましょう。

《関連記事》
セキュリティ対策はばっちり? セッションとCookieの違いとPHPでの使い方をご紹介!

記事をシェア
MOST VIEWED ARTICLES