いにしえの時代、PHPはセッションハイジャックに致命的に脆弱でした。
かつてのPHPはhttp://example.com/?phpsessid=hoge
というURLでアクセスするとhoge
というセッションIDでセッションが始まるという仕様であり、これは仕様というかセッション固定攻撃という脆弱性そのものです。
そもそもなんでこんな仕様があったのかというと歴史的経緯というやつです。
PHPが誕生した時代は、そもそもCookieに対応していないブラウザ・端末が普通に存在していた時代でした。
たとえばスマホ以前に存在したガラケーはほとんどがCookieに未対応です。
そんな端末・ブラウザでもログインしたりショッピングカートを使いたい、そんな場合はどうすればいいか。
そこでURLにセッションIDを載せて運用しよう、という発想が生まれました。
この発想は当時はPHP以外の言語でも行われていたのですが、すぐに問題が発覚しました。
URLをコピーすると通常はhttps://qiita.com/rana_kualu/items/4118511b430fff0135d1
のようになるわけですが、URLにセッションIDを乗せている場合はhttps://qiita.com/rana_kualu/items/4118511b430fff0135d1?PHPSESSID=5f4dcc3b5aa765d61d8327deb882cf99
のようになります。
で、うっかりこれをこのまま共有してしまうと、他者が自分としてログインできてなりすましができてしまうというわけです。
これが実装された当時はそもそもセキュリティなどほとんど誰も気に留めないおおらかな時代だったので、仕方ないといえば仕方ないんですけどね。
しかしその後問題が知れ渡るにつれ、他言語ではこの機能自体を削除するようになり、PHPでも設定を増やしたり、デフォルト値を安全側に倒したりと問題が起きにくいようにしてきました。
が、PHP8.3時点でもいまだに、設定を甘くすることによって脆弱にすることが可能です。
しかしまあ、いいかげんCookieを使えない環境も絶滅したし機も熟したということで、システム的に脆弱にすること自体を不可能にしようということになりました。
このRFCは既に受理されており、PHP9以降、PHPはセッション固定攻撃から完全に解き放たれます。
スケジュールとしてはPHP8.4でDeprecate、PHP9で機能自体の削除という流れになります。
以下は該当のRFC、Deprecate GET/POST sessionsの日本語訳です。
PHP RFC: Deprecate GET/POST sessions
Introduction
PHPは、セッションIDを継続する方法を2種類提供しています。
Cookieと、URLパラメータです。
このうちCookieは事実上の標準となっており、推奨される方法です。
URLによるパラメータは、使い勝手と安全性の両方の面で問題がありますが、Cookieが常に使用できるとは限らなかったことから、代替オプションとしてメカニズムを供給してきました。
このフォールバックを容易にするため、use_trans_sid
という機能が用意されています。
この機能は、全てのURLに自動的にセッションIDを埋め込みます。
これにより、Cookieが有効でない場合はURLパラメータを使ったセッションにシームレスに切り替えることができます。
GET/POSTパラメータにセッションIDを埋め込むことは、一般的には悪い方法だと考えられています。
理由としてはたとえばWhy is passing the session id as URL parameter insecure?を参照してください。
Proposal
GET/POSTパラメータで受け取ったセッションIDを使ったセッションの有効化、およびURLへのセッションID自動埋め込みの両方を非推奨とします。
現在、これらの設定は初期状態で無効になっています、
従って、機能が有効になっている場合にのみ廃止の警告を表示することにします。
以下のデフォルト設定では、非推奨の警告は発生しません。
session.use_only_cookies=On
session.use_trans_sid=Off
デフォルト設定から変更されている場合は警告が発生します。
session.use_only_cookies=Off ; Will generate a deprecation warning
session.use_trans_sid=On ; Will generate a deprecation warning
以下のini設定項目は非推奨になります。
・session.use_only_cookies
・session.use_trans_sid
・session.trans_sid_tags
・session.trans_sid_hosts
・session.referer_check
関数session_startの引数として渡すことも非推奨となります。
また定数SIDも、このRFCの一環として非推奨になります。
そして、PHP9.0ではこれらの機能が完全に削除されます。
上記のini設定、および定数SIDも削除されます。
session.use_cookies = Off
Cookieを発行せずにCookieセッションを使う用途があったのかは定かではありません。
しかし、この設定を使うとPSR-7を遵守することができます。
session.use_cookies
を無効にすると、PHPはセッションを開始してもセッションIDのCookieを発行しません。
その後都合のいいときにセッションIDのCookieを発行する役割は、開発者にあります。
このini設定は、本RFCに影響を受けません。
Backward Incompatible Changes
PHP8.4では、非推奨のアラートが出る以外、下位互換性のない変更点はありません。
ただし、PHP9.0では機能自体が使用できなくなります。
PHP9.0以降でURL埋め込みセッションを使いたい場合は、ユーザランドで実装する必要があります。
URLパラメータからのセッションID読み込みも行わなくなるので、session_idを用いて自力で実装する必要があります。
Unaffected Functionality
関数output_add_rewrite_varは影響を受けません。
ini設定session.use_cookies
を使用した、自力でのCookie制御は今後も引き続き可能です。
Version
PHP8.4でDeprecate。
PHP9で機能削除。
Vote
投票期間は2024/04/09~2024/04/23、投票の2/3の賛成で受理されます。
本RFCは賛成29反対0の全会一致で可決されました。
感想
ガラケーもとっくに滅びたし、今さらこんな機能があったところで事故の元でしかないので削除は妥当なところでしょう。
これに依存しているサイトなんてとっくに絶滅しているとは思いますが、万一残っているようであれば今のうちに対処しておきましょう。
まあ対処と言っても、よほどおかしなことでもしていないかぎり、ini設定をデフォルトにするだけで自動的にCookie制御になりますけどね。
それにしてもoutput_add_rewrite_varなんて関数初めて知ったわ。
a href
のURLやform
のパラメータに値を自動で追加してくれるという、HTML専用にもほどがある関数です。
他言語では言語仕様に入ってくることなど絶対ないであろう、利便性に全振りしたPHP言語ならではの機能ですね。