Bug(バグ) #2440
完了携帯版で外部サイトのURLへリダイレクトする処理を記述すると、リダイレクト先のURLにセッションIDが付与されてしまう場合がある
100%
説明
Overview (現象)¶
携帯版(mobile_frontend アプリケーション内)で外部URLへリダイレクトする処理を記述すると、Cookie を利用できない携帯端末でアクセスした際に、リダイレクト先の URL のパラメーターとしてセッションIDが自動的に付与されてしまいます。
例えば、アクション内に $this->redirect('http://externalsite.example.com/');
のように記述した場合がこれに該当し、このときリダイレクト先の URL が http://externalsite.example.com/?OpenPNE_mobile_frontend=XXX
のようになってしまいます。
mobile_frontend のアクション内でこの問題を回避してリダイレクト処理を記述するには、Location ヘッダーを送信する処理を自前で記述する方法くらいしか思いつかず、mobile_frontend 内にリダイレクト処理を記述している場合のほとんどこの問題の発生条件に該当するのではないかと思います。
OpenPNE 3.6RC1 で現象を確認しましたが、原因となっている箇所は OpenPNE 3.0 〜 3.7 まで同じ実装となっており、現行の OpenPNE 3 のすべてのバージョンで発生すると思われます。
携帯版で信頼できない外部URLへリダイレクトする際には、既存のセッションを無効にした上でおこなう必要があり、その場合には付与されたセッションIDによる攻撃は成立せず、セキュリティ上の問題はありません。(また、たとえ本チケットの問題を修正したとしても、リファラーからセッションIDが漏えいする危険があるため、既存のセッションが有効な状態で携帯版のログイン後ページから信頼できない外部URLへ直接リダイレクトしてはなりません。)
ただし、付与されるのが無効なセッションIDであったとしても、不要なURLパラメーターが強制的に付与されてしまうのは問題であるため、通常のバグとして報告しました。
Causes (原因)¶
opMobileFrontWebController::redirect() で渡された URL の内容によらず、強制的にリダイレクト先の URL パラメーターにセッションIDを追加しているため。
Way to fix (修正内容)¶
opMobileFrontWebController::redirect() に渡された URL が絶対URLである場合、URL は外部サイトを指していると仮定して、セッションIDのパラメーターをリダイレクト先のURLに付与しないよう修正します。
絶対URLであるからと言って外部サイトを指しているとは限らないですし、逆に絶対URLでないからと言って外部サイトを指していないとも限らないですが、本チケットでの修正対象を絶対URLの場合としたのは、PHP の session.use_trans_sid の仕様に合わせるためです。
(参考)PHP: セッションIDの受渡し
http://www.php.net/manual/ja/session.idpassing.php
ここで絶対URLというのは、 RFC 3986 : 4.3. Absolute URI で定義されている absolute-URI の条件を満たすURLで、scheme(http や https)から始まるURLです。
よって、以下のようなURLについてはこのチケットでは修正対象としません。
- foo (相対パス)
- /bar (絶対パス)
- //hoge.com (スキームを省略したURL)
これらはいずれも PHP の session.use_trans_sid でも相対URL扱いをされ、セッションIDが付与される対象となります。(このうち、相対パス形式の指定は redirect() メソッドの引数として渡した場合は、symfony の内部 URI とみなされるため HTML 内に直接書いた場合とは意味が異なりますが、セッションIDが付与されるかどうかの判定に関しては同じ結果となります。)
この修正以後も、開発者は mobile_frontend 内で絶対URL以外の形式で外部サイトを指す URL を安易に利用するべきではありません。これはリダイレクト先として指定する URL に限らず、PHP の session.use_trans_sid で変換対象となる HTML 内の URL にも当てはまります。
一方、この修正により、サイト内部の URL を絶対URLで記述している場合、セッションIDのパラメーターが付与されなくなるため、正常に動作しなくなる可能性があります。ただ、 redirect() メソッドを利用する際に OpenPNE (symfony) 内部の URL を指定するのに絶対URLを使うメリットはほとんどないと思われるため、このようなケースは珍しいと考えられます。仮にこのようなケースに該当する場合は、symfony の内部 URI 形式を利用するようにするか、もしくは、自力でセッションIDを付与するようにする必要があります。