なぜPHPアプリにセキュリティホールが多いのか?

第25回 PHPのアキレス腱 ── セッション管理

この記事を読むのに必要な時間:およそ 4.5 分

PHPにはHTTPセッション管理モジュールが標準で付いてきます。このセッションモジュールには非常に重大なセキュリティ上の脆弱性が修正されずに残っています。その脆弱性とはセッションアダプションです。

セッションアダプションとは,セッション固定化攻撃に利用される脆弱性です。PHPのセッション管理モジュールがセッションアダプションに脆弱であることは,かなり以前,何年も前から知られています。しかし,開発者の理解不足より脆弱性が放置されたままになっています。

セッションアダプションとは

セッションアダプションとは,ブラウザ等から送信された未初期化セッションIDをそのまま利用してセッションを初期化してしまう脆弱性です。ユーザが送信してきたIDでも第三者に予想できない文字列であれば大丈夫なのでは?と考える方もいると思います。その通りで第三者に予想できなければ問題ないですし,仮に予想できてもログインする際に別のセッションIDに変更できれば問題にはなりません。

セッションアダプションを理解するためにもっとも分かりやすい例は,URLやフォームに埋め込んだセッションIDを有効にしている場合の攻撃手順です。

URLベースのセッションアダプション攻撃

攻撃者はURLにセッションIDを埋め込んだメールやページを作成して,被害者にクリックさせます。セッションIDはURLに埋め込んであるので,セッションIDがランダムな文字列であっても攻撃にはとっては既知のセッションIDとなります。

  • http://target.example.com/?PHPSESSID=1234567890

セッションアダプションに脆弱なセッション管理機構は,URLに記載されたセッションIDによって初期化します※1)。このため,攻撃者は有効なセッションIDを知るためにランダムなセッションIDを試さなくても,攻撃者が発行したセッションIDの中から有効なセッションIDを探すことができます。

※1

セッションアダプションに脆弱なセッション管理なので,存在しないセッションIDであれば新規に初期化すべきところを既知のセッションIDで初期化していまうのです。

(攻撃用の)セッションIDはメールごとやリクエストごとに別々のIDを使ってもよいですし,WebページならクリックのたびにJavaScriptを利用してユニークなセッションIDを与えても構いません。

Webページであれば,XMLHTTPRequestを利用してJavaScriptに一手間かければ,同じユーザには常に同じセッションIDで初期化するようにもできます。どのセッションIDが有効であるのか,データベースで管理することも可能です。

このように有効なセッションIDが分かれば,攻撃者は他人に成りすましてWebアカウントを利用できるようになります。

セッションアダプション対策

一般的にはセッションアダプション対策には,ログイン時にセッションIDを再生成すればよい,と解説されています。ログイン処理の前に,セッションIDを作り直す関数を呼び出すだけです。

例:セッションIDの再生成
session_regenerate_id();

PHPの場合,URLベースのだけのセッション管理をしていれば,PHPのセッション管理モジュールを使っていても,セッションIDの再生成によりセッションアダプション攻撃はできなくなります。

注意:URLベースのセッション管理はセッションID漏洩の問題をどうしても回避できないので,通常は使うべきではありません。URLベースのセッションIDのほうが安全ということではありません。

筆者が執筆したWebアプリセキュリティ対策入門でも,ログイン時にセッションIDを再生成するよう記載しています。実はこの対策だけでは不十分であることは,筆者がWebアプリセキュリティ対策入門を執筆した時点(2005年末)でも知っていました。筆者がこの本を書いている時点では,近い将来リリースされるPHPでセッションアダプション脆弱性が修正されると考えていたため解説を省略していました。

しかし,実際には現在に至るまでPHPのセッションモジュールのセッションアダプション脆弱性は修正されないままになっています。このために,本来はsession_regenerate_id関数をログイン処理を行う前に呼び出すだけでよいはずのログイン処理に,脆弱性に対応するための余計な手間が必要となっています。

脆弱性への対応法は最後に紹介します。まずはより現実的な脅威であるクッキーベースのセッション管理がなぜ(セッションアダプションに関して)危険であるのか解説します。筆者は個別のブラウザとアプリケーションやその構成に対して,どの攻撃方法が有効であるか知っています。しかし,この連載は攻撃方法を指南するための連載ではないので,個別かつ具体的な攻撃方法は解説しません。筆者が解説しないから,安全であるかというとそうではありません。

この連載を読まれているWeb開発者くらいの,通常のWebアプリケーション開発者のスキルがあれば,ここに書いてある攻撃方法は理解できます。開発者以外の方がこの記事を読まれていることは少ないと思いますが,条件が整っていれば攻撃は非常に簡単に行えると理解してください。

セッションアダプションとクッキー

先ほど「URLベースのセッション管理であれば,session_regenerate_id関数でセッションIDを再生成すれば,セッションアダプションの影響を受けない」と解説しました。実際に,URLベースのセッション管理だけを利用し,適切なログイン処理を行っていれば,これから解説する脆弱性の影響を受けません。しかし,現在のPHPのデフォルト設定では,別のセキュリティ上の理由から,URLベースのセッション管理はデフォルトでは無効に設定されています。

通常のセッション管理はクッキーを利用して行われます。ブラウザのクッキーの取り扱いの仕様により,セッションアダプションに脆弱なセッション管理機構ではsession_regenerate_id関数を呼び出してもセッションアダプション脆弱性を回避できない状態が複数存在します。

クッキーの仕様

セッションアダプションがクッキーベースのセッション管理の場合にセキュリティ上の問題となる原因は,クッキーの仕様にあります。クッキーの仕様により,同じURLであっても複数のクッキー値を持つことができます。

例えば,

  • http://blog.ohgaki.net/2009/

であれば,最大4つのクッキー値 ── 同じ変数名(クッキー名)で4つの値 ── を持つことができます。

  • blog.ohgaki.net ドメインに対して/パスと/2009/パスの2つのクッキー
  • ohgaki.net ドメインに対して/パスと/2009/パスの2つのクッキー

これは,PHPのsessionモジュールのデフォルトのセッション名であるPHPSESSIDに4つの異なるクッキーを与えられることを意味します。

すべてのブラウザでどのクッキーが優先されるのか決まっており,一つのクッキーだけが送信されればよいのですが,現実は違います。ブラウザは同じクッキー名が複数ドメインや複数パスで設定されている場合,すべてのクッキーをWebサーバに送信します。ブラウザはクッキー名と値のペアを設定されている数だけ送信します。分かりやすくいうと,どのクッキーがどのドメインのどのパス用に設定されたのか,サーバ側では分からない形で,ブラウザの好き勝手な順序で送信します。

この仕様がセッションアダプションに脆弱なセッション管理機構に致命的なセキュリティ問題の原因となっています。

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書

コメント

コメントの記入