YAPC::Asia Tokyo 2015 Lightning Talks Day 1
http://yapcasia.org/2015/talk/show/9c87ba50-3c17-11e5-9f50-22d57d574c3a
(昔の) PHP が誇った最高の機能 register globalsその真実そして未来へ@gongoZ (Wataru MIYAGUNI)YAPC::Asia Tokyo 2015
View Slide
自己紹介 宮國 渡 ごんご おきなわ @gongoZ github.com/gongo Emacs で PHPer
自己紹介(Con’t) 肉体言語 Tython 開発者 世界で唯一 Hello, World を実行できた人間
自己紹介(Con’t) Emacs で書いてる文章の中で「一句」を教えてくれるEmacs Lisp http://qiita.com/gongo/items/a0809d6e3bb6a4d925eb
実用性のないものを作るのが趣味
そんなわけでPHP の話します
みなさんPHP 使っていますか
みなさんPHP ≥ 5.4 使っていますか
お知らせですPHP 5.4 のセキュリティサポートは2015年9月14日までです忘れずに PHP 5.5 以上にアップデートしましょうSee: PHP: Supported Versions
あらためて、みなさんPHP 使っていますか
あらためて、みなさんPHP < 5.4 使ってるんですか
あらためて、みなさんどうして 5.4 に行かないんですか
_人人人人人人_> 5.3 の壁 < ̄YYYYYY ̄
See: PHP: 下位互換性のない変更点 - Manual
register globals
register globals とはregister globals を on とした場合、この機能により、HTML フォームから投稿される変数と同時に、あらゆる種類の変数がスクリプトに注入されることになります。これは、PHP においては変数の初期化が不要であるということにも関係し、 安全でないコードを書くことが極めて容易になるということを意味します。See: PHP: グローバル変数の登録機能の使用法 - Manual
例register globals = off
例register globals = on
未だ on のアプリの特徴日頃からグローバル変数を嗜んでいるクラスが存在しなかった時代からの遺産とか
off にできない理由の一つ全てのグローバル変数をチェックして自分で定義したやつはそのままにしておいてリクエストデータであれば $_GET などのリクエストデータを扱うスーパーグローバル変数に置き換える作業をしないとああああああああめんどくさいあああああああああああ
めんどくさい例目の前にあるグローバル変数が リクエストデータ なのかスクリプトで定義した変数 なのかがわからない
人は怠惰であるどうにか最小限の変更で(古いコードのまま)PHP 5.4 に上げたいregister_globals を再現するいい方法ないの???
人は怠惰であるどうにか最小限の変更で(古いコードのまま)PHP 5.4 に上げたいregister_globals を再現するいい方法ないの???あるぞ!!超簡単だぜ!!
php.net が教える秘策This will emulate register globals On.See: PHP: Miscellaneous Questions - Manual
秘策解説(1) register globals が影響するスーパーグローバル変数 (連想配列) を順番に見て
秘策解説(2) extract() を使って現在のスコープ (この場合はグローバル) に、キーと同じ名前の変数をアサインする
さきほどのコードをentrypoint に書いておけばregister globals っぽい動きが再現できます
とてもお手軽なのです
とてもお手軽なこの方法は
残念ながら間違ってます
使ってはいけない
register globals にはphp.net に載っていない隠された仕様がある 隠しているわけではないと思うが書かれてない 自分が見つけれていないだけだと信じてる
その1$_FILES
$ FILES とはHTTP POST メソッドで現在のスクリプトにアップロードされた項目の連想配列です。See: PHP: $ FILES - Manual
$ FILES 例 (1)
$ FILES 例 (2)POST すると $ FILES はこうなります
register globals 効果により
_人人人人人人人人人人_> $upload_tmp_name <> にしとけよ!! < ̄YYYYYYYYYY ̄
おまけregister globals が on の状態で $ FILES に対してextract() を実行して EXTR SKIP を指定すると、その結果に驚くことでしょう 。See: PHP: extract - Manual
おまけregister globals が on の状態で $ FILES に対してextract() を実行して EXTR SKIP を指定すると、その結果に驚くことでしょう 。See: PHP: extract - Manualちゃんと書け
$ FILES まとめ そのまま extract() 使うと死ぬ tmp_name だけ規則違うから注意なSee: http://gongo.hatenablog.com/entry/2014/10/02/211520
その2$_SESSION
$ SESSION とは現在のスクリプトで使用できるセッション変数を含む連想配列です。See: PHP: $ SESSION - Manual
$ SESSION も対象ですEGPCS(Environment, GET, POST, Cookie, Server)変数を グローバル変数として登録するかどうかを指定します。See: PHP: register globals - ManualSession とは一言も書いてない けどSession も対象です
$ SESSION + register globals
$ SESSIONS まとめ リファレンス渡しされるので注意な session_start() のタイミングでグローバル変数にアサインされるので、同キー名があれば (たぶん) EGPCS よりも強い(上書きする) 余談ですが EGPCS の順番は variables order の設定で決まるSee: http://gongo.hatenablog.com/entry/2014/12/24/132841
そんなわけで register globals の仕様を深く知ることができました もし PHP 5.3 → 5.4 を挑戦している方は、グローバル変数と引き続きがんばってください
「それでもめんどくさい」
「仕組みはわかったからどうすれば 5.4 に上げられるの?」
そんな貴方に便利な!! github.com/gongo/merciful-polluter packagist.org/packages/gongo/merciful-pollutermerciful polluter
そんな貴方に便利な!! github.com/gongo/merciful-polluter packagist.org/packages/gongo/merciful-pollutermerciful polluter慈悲深い汚染 (直訳)
Installation$ composer require gongo/merciful-polluterpackagist に登録済みなので composer で Get できる
Usage(new Gongo\MercifulPolluter\Request)->pollute();// main routinepollute() を呼び出すとグローバル変数へのアサインが行われる
Usage (with $ SESSION)(new Gongo\MercifulPolluter\Request)->pollute();// ...session_start();(new Gongo\MercifulPolluter\Session)->pollute();// ...
Usage (with magic quotes gpc)$request = new Gongo\MercifulPolluter\Request;$request->enableMagicQuotesGpc();$request->pollute();// ...
Supported VersionSee: merciful-polluter/.travis.yml at master gongo/merciful-polluter
Supported Versionいつまでも使える!!
まとめのまとめ はやく PHP 5.4 以上にしよう 脆弱性残ったままなので危険です merciful polluter 使わない未来にしていこう スーパーグローバル変数汚染は防いでいるものの、それ以外は通常の仕様のままなのでやはり危険です PHP 7 に register globals を持っていかないように 7 に相応しくない
まとめのまとめ はやく PHP 5.4 以上にしよう 脆弱性残ったままなので危険です merciful polluter 使わない未来にしていこう スーパーグローバル変数汚染は防いでいるものの、それ以外は通常の仕様のままなのでやはり危険です PHP 7 に register globals を持っていかないように 7 に相応しくないno register globals, now PHP