セッションアダプション脆弱性がないセッション管理が必要な理由 » |
セッションアダプションとセッションフィクセイションとセッションハイジャックの違いとは
徳丸さんがセッションアダプションをなくしても、セッションハイジャックが出来るのでsession_regenerate_id(true) (trueを付けると古いセッションデータは削除される)をしなければならないという記事を書かれています。
セッションアダプションがなくてもセッションフィクセイション攻撃は可能
http://tumblr.tokumaru.org/post/37676352092/session-adoption-and-session-fixation
まず結論を書きます。徳丸さんが「セッションフィクセイション攻撃は可能」と言われているのは間違いです。正しくは「セッションハイジャックが可能」です。
この議論は別々の異なる脆弱性を一緒にした議論で正しい議論とは言えません。セッションアダプション、セッションフィクセイション、セッションハイジャックとはどのような脆弱性なのか整理して議論する必要があります。
...
セッションアダプション
未初期化のセッションIDを正規のセッションIDとして受け入れてしまうセッション管理機構の脆弱性
セッションフィクセイション
セッションIDの固定化が可能な状態を利用して、本来未知であるべきセッションIDを既知のセッションIDに固定化してしまう脆弱性
セッションハイジャック
ユーザが現在利用しているセッションIDを何らかの手法(盗聴、Javascriptインジェクション、セッションフィクセイションなど脆弱性)によって盗み取る攻撃
セッションアダプション、セッションフィクセイション、セッションハイジャックと書くのは長いので以下はアダプション、フィクセイション、ハイジャックとして説明します。
アダプションとフィクセイションとハイジャックの関係
アダプション脆弱性はフィクセイションを行える脆弱性の一種です。できの悪いセッション管理機構ではアダプション脆弱性が無くてもフィクセイションが可能です。実際にあったフィクセイションの例には
$session_id = sha1('username' . 'password'.'random string');
と、ユーザ名とパスワードからハッシュ値を取得してセッションIDとして利用していたシステムがありました。本当にできの悪いセッション管理機構ではsaltとなる'random string'さえ無いハッシュ値をセッションIDにしていました。saltさえ無い場合、比較的簡単にハッシュ値からブルートフォース攻撃でパスワードさえクラックできてしまいます。
このようなセッション管理ではセッションIDは常に同じIDになってしまいます。「IDが固定化」されるのでフィクセイション(固定化)と呼ばれています。
アダプション脆弱性を利用した攻撃はフィクセイション脆弱性を利用した攻撃の一種です。さきほど説明したフィクセイション脆弱性はセッションIDの生成が固定化してしまう実装ですが、アダプション脆弱性があると任意のセッションIDに固定化できてしまう場合があります。アダプションを利用したフィクセイション攻撃です。
ハイジャックとはセッションIDを何らかの手法を用いて盗む攻撃です。ハイジャックはセッション管理機構の脆弱性に関係なく実行できる攻撃です。セッション管理機構にフィクセイション脆弱性がある場合はより簡単に実行できる攻撃です。セッションIDを盗むには、盗聴、フィクセイション、Javascriptなどにより盗む、ページやURIなどに含まれているセッションIDを盗む、などの手法を用います。
徳丸さんもセキュリティスペシャリストの一人なので上記の事は理解していて
上記のセッションフィクセイションの攻撃シナリオでは、セッションアダプションは使っていません。その代わりに、攻撃者は、攻撃対象サイトに先にアクセスして、「有効なセッションID」を取得し、それを被害者のブラウザにセットしています。元々が、攻撃対象サイトが発行したセッションIDなので、PHPはそのまま当然のように受け入れます。
「アダプションは使っていません」と書いています。
徳丸さんの攻撃パターンは、「これはXSS攻撃用の罠のURLを生成しているのです。」と書いてあるとおりJavascriptインジェクションを利用して攻撃者に既知である有効なセッションIDを作っています。これはそもそも私も解説している攻撃パターンと全く同じです。(違いはガーベッジコレクションされているか、いないかだけです)
有効なセッションIDであれば受け入れるのは当然です。仮にhttponly属性でJavascriptからクッキーを保護していても、Javascriptインジェクションに脆弱性である時点でそのアプリケーションの情報は盗めてしまいます。セッションは盗めなくてもDOMでページコンテンツを盗めば良いだけです。
では、どのような場合にアダプション脆弱性を無くしたセッション管理機構はより安全になるのでしょうか?それはアダプション脆弱性の定義を見れば分かります。アダプションは「未初期化のセッションIDを正規のセッションIDとして受け入れてしまうセッション管理機構の脆弱性」です。セッションIDが未初期化である場合にセッションIDが保護されます。
app1.example.comやapp2.example.comとドメインによってアプリケーションやユーザ(ホスティングなど)を分けている場合、www.example.com/app1やwww.example.com/app2とパスによってアプリケーションやユーザを分けている場合に有効です。このようなアプリケーションやユーザの分割はよくある構成です。
このような構成にし、アプリケーション(またはユーザ)を分割しているとします。ここではapp1とapp2が別のセッションセーブパス(session.save_path)を持っているとします。同じサーバでユーザやアプリケーションを分割する場合、session.save_pathも分割するのがベストプラクティスなので覚えておきましょう。session.save_pathで指定するのはセッションデータのデータベースとなる場所(DBやファイル)です。ユーザが両方のアプリケーションを利用している場合でも、セッションセーブパスが異なればセッションIDが同じでも、app1とapp2で利用されるセッションデータベースは異なります。Javascriptインジェクションなどを使いapp1からapp2で使うセッションIDを指定しても、app2のセッションデータベースでは未初期化です。アダプション脆弱なセッション管理機構の場合、未初期化のセッションIDを受け入れてしまいますが、脆弱性がないセッション管理機構の場合は新しいIDが生成されapp2は守られます。
ドメインやパスでアプリケーションやユーザを分割する構成はよく見かける構成です。アダプション脆弱性が無いセッション管理機構を用いベストプラクティス通りにセッションデータベースを分割していれば、仮にプログラマのミスや一見判別しづらいコード実行パスを変更できてしまう脆弱性がありsession_regenerate_idを呼び出さない問題があっても、他のユーザやアプリケーションの脆弱性の影響を受けなくなります。
システム管理用のアプリケーションには、システム管理者や開発者のみが使うことを前提にセキュリティが甘いアプリケーションが多い傾向にあります。パスやドメインで分割されている方も多いでしょう。同じサーバにインストールしている方は、これを機会にsession.save_pathの設定を再確認してみると良いかも知れません。
まとめ
徳丸さんは「セッションアダプションをなくしても、セッションフィクセイション攻撃は可能」としていますが同じセッションデータベースを共有しているシステムなのでアダプションと呼ぶのは間違いです。ハイジャックの一種、と分類すべきです。
セッションIDはWebセキュリティの要なので、プログラムの不具合によって盗めてしまう脆弱性は極力排除すべきである、とすることに異論がある方は居ないでしょう。徳丸さんの例からも分かるようにベストプラクティスと呼ばれるコーディングや構成に従う事は非常に重要です。私もsession_regenerate_idでイベント毎、定期的にセッションIDを更新することをベストプラクティスとしてお勧めしています。Webシステムの仕様上の問題で直せない問題などもありますが、直せる脆弱性は全て直す、これもベストプラクティスです。致命的な問題の攻撃パスと成り得る脆弱性が直せるのに直さないで大丈夫です、という開発者が作っているソフトウェアを使いたい、と思う方は少ないはずです。
ところで私が考えるSQLインジェクションを防ぐ為にプログラマに教えるべきベストプラクティスは徳丸さんとは異なります。これも、そのうちまた議論したいと思います。プレイスホルダにとらわれ過ぎていて、フォーマット文字列をプレイスホルダと同じだと勘違い(?)したケースは私も興味深かったです。
セッション管理のベストプラクティスもまとめておいた方が良さそうです。これはオライリーさんのPHPセキュリティ本の中でまとめることにしています。
徳丸さんのブログもあまり読まずに、サクッと書いたエントリなので何か勘違いしていたり、間違っている事があるかも知れません。もし気になったらツイッターやフェースブック、コメントなどで教えてください。
関連エントリ
補足
セッションデータベースが同じでも、期限切れで削除されている場合はアダプション脆弱性が無いセッション管理機構なら保護されます。このアダプション脆弱性を利用して攻撃する場合、有効期限が長いセッションIDクッキーを利用して攻撃すると考えられるます。session_regenerate_idを呼ばない脆弱なアプリがあり、データベースが同じ場合でも保護できる場合もあるということです。セッションの有効期限を短くする事はベストプラクティスです。セッションクッキーを使ったり、セッションIDをイベント毎や定期的に変更したり、ガーベッジコレクションを短めに設定する(セッションIDを定期的に変更するタイミングに合わせる)、などがベストプラクティスです。
補足2
徳丸さんの記事よく読まないで書いている、と最初にエントリを書いたときに書きましたが。エントリのタイトル名をよく読んでいませんでした。セッションアダプションとセッションハイジャックを間違えてタイトルに書いているとは思っていなかったので勘違いして書いていました。「セッションアダプションをなくしても、セッションフィクセイション攻撃は可能」これは明らかな間違いなので本文の一部を修正しました。
3 コメント
とありますが、徳丸さんのプログラムを見る限り、xssの方は踏み台としてのみ使用しデータベースどころかPHPすら使ってないと思います。
徳丸さんのプログラムの勘所は、攻撃者へログイン失敗で発行された「正規のセッションID」を他の人ブラウザへ「ログイン前に設定」して、その人の「ログイン後のセッションID」として使用させるという点だと思います。
故に、session_regenerate_id()を使用しないと防げないと言ってるんじゃありませんか?
徳丸さんが指摘しているのは、有効なセッションIDがある場合、session_regenerate_id(true) (セッションデータを削除するこのtrueは重要です。本文に書いていませんが、重要なプラクティスです)を呼ばないとセッションハイジャックが出来る、という点では?このセッションハイジャックはアダプション脆弱性の有無に関係なく、セッション管理手法が悪いと発生する問題です。(ご指摘の通り、PHPというインフラの問題でなく、プログラマやフレームワークの問題)
しかし、これは未初期化のIDを受け入れさせるアダプション脆弱性を使った攻撃ではありません。セキュリティ専門家以外の方にはあまり意味がなく細かい事で恐縮ですが、徳丸さんはセキュリティ専門家なので、違いますよ、と指摘しているのです。
データベースが同じ場合、ガーベッジコレクションされる前なら防御されない点について最初から異論はありません。しかし、だからといってアダプション脆弱性は直さなくてもよい脆弱性ということにはなりません。本来脆弱なセッション管理機構でなければ、ないハズのアタックパスが出来る。これを修正する事が重要ではないでしょうか?
そもそも私はこのPHPのアダプション脆弱性を「修正する為に防御できるケース」を広めてPHPに取り込もう、としてたので防御できないケースを解説していませんでした。不親切だと言われるかも知れませんが、わざわざ広める必要も無いと思っています。また、セッションIDを再生成することはアダプション脆弱性の有無に関わらず重要であると広めているいる事も理解してください。
少なくともPHPのアダプション脆弱性を直すまで、この事はあまり書きたくなかったのですが、セッションIDを更新するAPIを持たず(呼ばず)、セッションデータベースを共有しているWebシステムは、PHPに限らず結構あるのではないかな?と思っています。その場合、ドメインやパスでアプリケーションを分離しているつもりでも、Javascriptインジェクションで「他のアプリ」のセッションIDを盗めてしまいます。PHPに限った事ではない、という指摘はその通りなので他のプラットフォームでWeb開発を行っている方もセッションIDを正しく再生成してください。(PHPの様に、古いデータを削除できる仕組みであれば良いのですが。session_regenerate_id()にtrueオプションが後で足された理由はそこにあるので)
PHP本体を開発する「PHP開発者」にとってアダプション脆弱性は「重大な脅威」でしょうか?私は重大な脅威だと考えています。セッションIDというセキュリティの要を明らかに守れるケースがあるにも関わらず、既知の攻撃パスを残し、攻撃を受けたユーザには重大な影響があるかも知れない脆弱性を放置することは、PHPプロジェクトに対する信頼性を大きく損なう問題だと考えています。(少なくとも私はかなりがっかりしてました。PHPプロジェクトへの貢献もほとんどしなくなるほどに。これだけじゃ無いのですけどね。)
脆弱性が「重大な脅威」であるか、でないか、は立場が違えば異なります。脆弱性に「影響されるかどうか」「影響した場合の結果」が判断基準になるでしょう。ですから影響されないようなPHPプログラムを使っている、書いている、一般のPHPユーザが重大な脅威ではない、と評価することに異論はありません。
「セキュリティ専門家」は「PHP開発者(PHP本体を開発する開発者)」の立場を共有すべきでは?と考えるのは私だけでしょうか?