脆弱性やセキュリティ対策について技術的な話ばかりしていたので「それで結局PHPのセッション管理どうすれば良いの?」と思われた方も多いと思います。簡単にまとめます。漏れや追記した方が良い事などがあったらご指摘ください。
-
セッションフィクセイションはアダプション脆弱性修正で防御可能
古いエントリを編集すると議論の流れが分かりづらくなるので、前のエントリをベースに新しいエントリを作って議論します。このエントリではアダプション脆弱性を修正すると、どのようなフィクセイション(ハイジャック)から防御されるのか解説します。安全なセッション管理には適切なユーザスクリプトが欠かせないので、全て防御できるわけではありませんが、有用性は理解頂けると思います。
セッションアダプションがなくてもセッションフィクセイション攻撃は可能
http://tumblr.tokumaru.org/post/37676352092/session-adoption-and-session-fixation
この議論は別々の異なる脆弱性を一緒にした議論で正しい議論とは言えません。セッションアダプション、セッションフィクセイション、セッションハイジャックとはどのような脆弱性なのか整理して議論する必要があります。議論を分り易くするため、これらの用語の定義は8年ほど前にPHPプロジェクトでこの問題が議論された時の定義を用います。
その上で、徳丸さんがツイッターで提示されたセッションフィクセイションの攻撃パターン(PDF)はアダプション脆弱性で攻撃できなくなることを解説します。論点を明確にする為、細かい部分の解説は省略しています。攻撃に必要な脆弱性は存在している事が前提です。ディフィニティブな解説では無いことを予めご理解下さい。
-
セッションアダプションとセッションフィクセイションとセッションハイジャックの違いとは
徳丸さんがセッションアダプションをなくしても、セッションハイジャックが出来るのでsession_regenerate_id(true) (trueを付けると古いセッションデータは削除される)をしなければならないという記事を書かれています。
セッションアダプションがなくてもセッションフィクセイション攻撃は可能
http://tumblr.tokumaru.org/post/37676352092/session-adoption-and-session-fixation
まず結論を書きます。徳丸さんが「セッションフィクセイション攻撃は可能」と言われているのは間違いです。正しくは「セッションハイジャックが可能」です。
この議論は別々の異なる脆弱性を一緒にした議論で正しい議論とは言えません。セッションアダプション、セッションフィクセイション、セッションハイジャックとはどのような脆弱性なのか整理して議論する必要があります。
-
セッションアダプション脆弱性がないセッション管理が必要な理由
徳丸さんから「ブログ読みました。サンプルも動かしました。問題は分かるのですが、セッションアダプションがないPHPだと、何が改善されるのかが分かりません。教えて下さい 」とあったのでツイッターで返信するには少し長いのでこちらに書きます。まだ直していない脆弱性を詳しく解説するのはあまりよくないのですが、今なら影響を受けるアプリはほぼないと思うので構わないでしょう。
まず前提として、Webサーバと同様にJavascriptからもクッキーが設定できます。Javascriptインジェクションに脆弱なコードがサイトに1つでもあると、サイト上のセッションアダプション脆弱性をもつアプリへの攻撃が可能になります。この攻撃を緩和する対策もありますが、それはそれ、これはこれなので省略します。
セッションアダプションに脆弱なセッション管理機構で困る代表的なケースは以下の通りでしょう。
- ログイン時にsession_regenerate_idを呼んでない
- 自動ログインなど通常のセッション用以外でsession_regenerate_idを呼んでいない
- session_regenerate_idを呼んでいても、途中で保存している
- session_regenerate_idを呼んでいても、途中で実行パスが変えられる
-
PHPのセッションアダプション脆弱性は修正して当然の脆弱性
PHPのセッションアダプション脆弱性がどのように影響するのか、広く誤解されているようです。セキュリティ専門家でも正しく理解していないので、一部のPHP開発者が正しく理解しなかったのは仕方ないのかも知れません。
Webセキュリティの第一人者の一人である徳丸氏は「PHPのセッションアダプション脆弱性は脅威ではない」と書いていますが、いろいろ間違いです。私は2005年頃から現在まで様々な機会に問題であると何度も繰り返し説明しており、しばらくすれば間違いに自分で気付くのでは?と思っていたので特に反論していませんでした。しかし、まだ気づかれていないようなので、幾つかある攻撃パターンのうち解りやすい例を1つだけ紹介しておきます。
-
知っているようで知らないプリペアードクエリ
PostgreSQL Advent Calender 2012用のエントリです。
PostgreSQLや他のDBMSを利用していてプリペアードクエリを知らない方は居ないと思いますが、プリペアードクエリを使いこなす為のTIPSです。役に立つかどうか、は多少疑問ですが、内部がどうなっているか知っているとなにかの役に立つかも知れません。時間的制約で多少端折っているところは勘弁してください。
完全なSQLインジェクション対策は以下を参照してください。
https://blog.ohgaki.net/complete-sql-injection-counter-measure
-
PROVE2の先行販売
PROVE2エンタープライズ版の先行販売を12/25日までの期間・数量限定で行なっています。PHP5.1/5.2をご利用中でPROVE2を運用・開発に組み込みたいとお考えの方は是非この機会にご購入ください。
-
PROVE2の紹介動画
PROVE for PHPへ紹介動画を掲載しました。PROVEの動作・操作を3分ほどで見て頂けます。より高解像度で見れるようYouTubeにHD版もアップロードしています。
PROVE for PHPはPHPの内部動作を記録・比較し、新しいバージョンで意図通りに動作しているか確認できるテスト・ツールです。PHPプロジェクトがソースコード管理システムをGitへ移行してから、予定通り毎月新しいリリースが公開されてます。PHPを最新の状態に保つ事はセキュリティ維持の為に書かせませんが、運用中のシステムのバージョンアップは容易ではありません。PROVEはそういったバージョンアップを簡単にします。
使い方は色々あります。
- PHPのバージョンアップ前後の動作確認
- 再帰テスト為のリクエスト送信をWebアプリに送信
- 実行内容を参照し問題の発生箇所を特定
PROVEはPHPの動作環境を記録した時と同じ状態にして、スクリプトを実行できます。この為、テストケースの作成はブラウザでアクセスするだけ、テストは記録したログを再生するだけで完了します。PHPのバグフィックスやセキュリティフィックスで動作が変わった場合、どこで動作が変わったのか簡単に分かります。リリースノートなどのみでは分からない動作変更も見つける事ができます。時間関数やファイル関数、データベース、ネットワークなど状態や外部リソースに依存する関数は実行をオーバーライドし、記録した時点の結果を返すことが出来ます。つまりmicrotime関数やsrand関数などに影響されずに、(PHPの動作が変わっていなければ)記録時点と同じ実行結果を得る事ができます。
PROVEのホームページで解説していない利用方法として、スマートフォンや携帯サイト開発での利用方法を紹介します。PROVEには「再帰テスト為のリクエスト送信をWebアプリに送信」する事ができます。スマートフォン、携帯サイトなどの場合、機種などの応じて異なるレスポンスを行う事が良くあります。PROVEの場合、PHPアプリにリクエストされた「リクエスト情報」がそのまま記録されます。これを再生することにより、繰り返しスマートフォンや携帯を使わずにこれらのデバイスを利用したテストを再現できます。
PROVEには前回記録した状態を再現・外部リソースに依存せずに動作する機能がありますが、この機能を利用しない状態でも利用できます。この場合、データベースやファイルなどの外部リソースをテストケース作成時と同じ状態にして実行し、PROVEによる再現機能を使わずにより広い範囲のPHP機能のテストを行う事も可能です。
プロキシやブラウザでWebアプリケーションの動作を記録するテストシステムと比べると、PHP内部の動作を全て記録するPROVEのテストは比較にならない程強力です。
PROVEの基本機能
- ブラウザからのリクエストの記録
- リクエストを処理した際のPHP動作の記録
- 全てのリクエスト情報(POST、GET、COOKIEなど)
- 出力(出力関数単位で習得可能)
- 関数呼び出し
- 関数戻り値
- セッション情報
- 記録したリクエストの再生
- 記録した時点の状態を再現
- 指定した関数のみ状態を再現
- 記録時点の状態を再現せずに実行
- 実行差分の参照
- 記録したログの参照
新しいPROVE2のベータ版が公開中です。ご興味がある方は是非一度お試しください。
ホームページ
ベータ版ダウンロード
-
PHPのStrict Sessionパッチ
のんびりしていた訳ではありませんが、PHP 5.4.1のブランチが作られたので慌ててStrict Sessionパッチを改訂しました。
master
https://gist.github.com/1379668
5.4
https://gist.github.com/2224196
5.3
https://gist.github.com/2224360以前、Gistに入れていたパッチとの違いは、
- PSモジュール(セッションセーブハンドラ)のAPIを変更しないように修正
(これにより使っているハンドラが対策済みかどうかは見て分かるようには出来なくなりました。その代りにmemcacheなどのサードパーティのセーブハンドラのコンパイル済みバイナリとの互換性を維持しています。) - セッションIDのコリージョン(衝突)を検出
(三回リトライしてもコリージョンする場合はエラー。通常、三回もコリージョンすることはまずあり得ません。)
となります。
PSモジュールを書く方(ユーザセーブハンドラ含む)はセッションをOPENする場合にセッションIDが初期化済みか、チェックする必要があります。
と、ここまで書いてパッチに多少問題がある事に気が付きました。自動生成する場合はコリージョンを検出していますが、session_regenerate_id()で生成する場合はコリージョンをチェックしていません。session_regenerate_id()を呼んだ時もチェックしないと片手落ちなので近いうちに修正します。
パッチを書いていてsession_write_close()してsession_start()をした場合、おかしくなることに気が付きました。困っている人が居るか、バグDBを検索するとやはり数人からバグレポートされていました。この件は別途に対応する事にします。
パッチを使ってみてくださる方、大募集です。ZTS、Non-ZTSの両方でUNITテストは実行していますが、Webサーバでテストしていません。動いたら、Twiterなどで良いので教えてください。よろしくお願いします。
このパッチについては、こちらをご覧ください。これは私が書いているのでおかしな英語があった場合、教えて頂けると助かります。
- PSモジュール(セッションセーブハンドラ)のAPIを変更しないように修正
-
OSC愛媛2012の資料 – PHP5.4とはどんなPHPなのか?
OSC愛媛2012の「PHP5.4とはどんなPHPなのか?」の資料を公開します。ポイントは以下の通り。
- PHP 5.4は基本的にはベターPHP5.3
- 互換性問題もあるが、一般に致命的な問題はない
- 全般にPHP5.4は速い
- 移行を考えている方は早い方が良い(使える期間が長くなる)
- ディストリビューションのPHPを使う、という選択もある(RHEL6 PHP5.3, Ubuntu LTS PHP5.4?)
プラットフォームの選択には様々な事情がありますが、Traitsはコードを効率良く再利用するには便利な機能です。さっと移行してしまうのも良いでしょう。
ところで、Traitsの例としてアクセサの実装例を紹介しています。
https://gist.github.com/1379592
しかし、次のPHPではC#風のアクセサ文法がサポートされる可能性があります。
https://wiki.php.net/rfc/propertygetsetsyntax
こちらの方が色々便利です。利用する場合は、このような文法が実装される可能性があることを理解した上で使うと良いと思います。
-
第二回 岡山PHP勉強会のスライド
第二回 岡山PHP勉強会のスライドです。
遅くなりました。多少追記したい部分があったのですが、取り敢えず公開します。
-
PHP: comma vs. dot #2
少し前にPHPのechoはカンマとドット、どちらの方が速い?というエントリを書きました。
http://blog.ohgaki.net/echo-comma-vs-dot
この時は長めの細切れな文字列を連結しています。カンマの方が2割ほど速い結果でした。古いPHPでは短く単純な文字列の場合もで速かった、と記憶していました。手元のPHP5.3の性能が気になったのでabで簡単に試してみました。
-
Git Hubの脆弱性とMass Asssignment
Git HubがMass Assignment脆弱性に脆弱で他のレポジトリが見れる状態だったらしい。問題は既に修正されています。
この脆弱性はRailsに限った事ではないし、古くからPHPを使っているユーザにとってはある意味懐かしい脆弱性でもあると思ったのでエントリを書いてみました。