PHP基礎 (14) セッションのセキュリティ問題と対策

PHP基礎 (14) セッションのセキュリティ問題と対策

セッション処理を標準で利用するとセッションIDをcookieでやり取りすることになります。
糸口として、セッションIDを狙った攻撃で重要な情報(例えばクレジットカードの暗証番号)を盗むことが可能になります。これが「セッションハイジャック」と呼ばれるものです。
dog4a

総当たり攻撃

セッションIDを盗む方法としてセッションIDを総当たり攻撃する手があります。これの対策はセッションの有効期間を短くする方法です。総当たりでの検索に1時間かかるなら有効期間を1時間未満にしてしまい、万が一正しいセッションIDが見つかってしまったとしてもすでに無効になっているようにするものです。

セッションの有効期限を変える

PHPデフォルトではセッションの有効時間は24分です。期限切れのファイルはガベージコレクションが収集してくれる仕組みです。新たにセッションを開始するごとにセッションファイルが新規で作られるのですから、これを掃除しなくてはそれこそ塵も積もれば山となるですね。それを解決するために、ゴミ収集が定期的に回収に来てくれるわけです。
定期的といってもどれくらいの頻度なのでしょうか。それは新たにセッションを開始するごとに気が向いたら回収に来る仕組みです。気が向いたらといえば文学的な表現ですが、ある確率でとした方が正しい表現です。
期限切れのセッションファイルのガベージコレクションは新たなセッション開始時にある確率で実施されるものです。

セッション開始時のある確率は session.gc_probability / session.gc_divisor と計算されるのでそれぞれの値を1とすると確率は100%になり、毎回ガベージコレクションが動きます。
次の例では1/100になります。30分で有効期限が切れ、新しいセッションが開始されたら1/100の確率でガベージコレクションを実施となります。
他のサイトやページに影響を受けないようにするには、session_save_pathでセッションファイルのデータを保存するパスが変更されます。

session_save_path("/tmp");
ini_set('session.gc_maxlifetime', 1800);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);
session_start(); //セッションスタートはここに書く。

セッションIDを盗む別の方法に盗聴があげられます。これはHTTPSによる暗号化通信を行えば回避できます。

XXSクロス・サイト・スクリプティング

HTML出力用サニタイズ

入力フォームに入力させたデータをブラウザに出力するような場合、入力された文字列に悪意のあるJavaScriptのコードが仕掛けられていたならそのままJavaScriptは実行されてしまいます。
それを防止する手段としてHTMLサニタイズを行います。htmlspecialchars を使用することでJavaScriptは実行されずにテキストとして表示されます。

string htmlspecialchars ( string $string [, int $flags = ENT_COMPAT | ENT_HTML401 [, string $encoding = "UTF-8" [, bool $double_encode = true ]]] )

脆弱性のある入力表示

実習(2) で使用した表示側のPHPファイルの一部を変更します。HTML側からはデータをPOST形式で送信しますが、受け取り側の名前の表示部分について、$_POST[]を使用せずにPOSTもGETにも使用できる$_REQUEST[]を使用してデータを受け取ります。
更にサニタイズするhtmlspecialcharsを使用せずにスクリプティングが可能な状態します。
表示ファイルの変更

$name = htmlspecialchars($_POST['name'], ENT_QUOTES); //これを下のように変更
$name = $_REQUEST['name']; //変更済み

入力するJavaScript

<script>alert("アラート表示");</script>

$_REQUESTはGET方式でもPOST方式でもデータを受け取れるスーパーグローバル変数です。
入力データをGET方式で受け取る仕組みの場合、スーパーグローバル変数は$_GETか$_REQUESTを使用します。

作成したサンプルをXAMPPで実行して試してみましょう。
htmlspecialcharsでサニタイズしない状況で名前の所にJavaScriptを入力してみます。 送信ボタンをクリックするとアラートが表示さるはずです。

XXS(クロス・サイト・スクリプティング)

今回作成したような脆弱性のあるWebアプリケーションを見つけたら、クラッカーは
有名な攻撃方法としてはXXS(クロス・サイト・スクリプティング)というテクニックを使用します。
これは、サイトAに記述されたJavaScriptプログラムをサイトB上で実行されるテクニックです。

先ほど作成した脆弱性のある入力システムにXXSを仕掛けてみましょう。

まず新規にHTMLファイルを作成します。

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>お試しサイト</title>
</head>
<body>
<h1>素敵なサイト</h1>
<p>あなたにとっても魅力のあるサイトです。下記をクリックしましょう。</p>
<p><a href='samplex.php?name=<script>alert("クラッカー!!");</script>'>ここへ行く</a></p>
</body>
</html>

この新規のHTMLは攻撃者が作成した罠のサイトと仮定します。
ユーザーはこのサイトのリンクをクリックすると先ほどの脆弱性のあるページに飛び、JavaScriptを実行してしまいます。
この例では「クラッカー!!」というアラートが表示されます。
もし、JavaScriptの内容をアラート表示ではなく、情報を抜き出すようなスクリプトならどうなるでしょうか。
このように罠のサイトから脆弱性のあるサイトに飛んでJavaScriptを実行する方法がXXSです。

セッションハイジャック

クラッカーは、セッション管理情報を総当たり攻撃や盗聴するなどして取得し、正規ユーザに成り済ましてあとはやりたい放題です。これがセッションハイジャックです。
そしてさらに悪質なSession Fixationという方法です。

セッションIDの固定化(Session Fixation)

悪意のある人は、先に示したクロス・サイト・スクリプティングで、自分が取得したセッションIDを善意の利用者のセッションIDに送り込みます。

これにより、善意の利用者に成りすましすることができるのです。

そのテクニックで使用されるJavaScriptが次のものです。

<a href="javascript:document.cookie='PHPSESSID=aaa;expires=Thu, 1-Jan-2014 00:00:00 GMT';location.href='login.php'">click me!</a>

“Session Fixation” のことで、セッションハイジャックの手法の一つです。

Session Fixationは通常のセッションハイジャックと発想が逆です。
つまり、善良なユーザーが使用するセッションID を攻撃者が指定し、善良なユーザーがそのセッションID でログインすると攻撃が成立するというものです。
ただし、セッション固定攻撃が成立するためには、攻撃者がセッション IDを指定することができる条件にある事と、ログインしてもセッション ID が変わらない事が必要です。

PHPでは、上の例で示したようにクエリに「PHPSESSID=……」という文字列をつけただけで、それをセッション ID として受け入れてしまう場合があります。つまり、攻撃者がセッション IDを指定することができてしまいます。

php.iniを変更してURLでセッションIDを受け付けなくすると防御できます。
次の例のようにPHPで一時的にphp.iniを変更することもできます。

ini_set('session.use_trans_sid', '1');
ini_set('session.use_only_cookies','1');
session_start(); //これはini_setの後に記述

更にログインが成功した時点でセッション IDを変えてしまうという方法です。