PHP-FPMでcgi.fix_pathinfo=0は必要なのか
tr;dr
PHP 5.3.9以降なら必要ない。
はじめに
NginxでPHPを動かす場合、大抵PHP-FPMを使うと思います。その設定方法を説明するほとんどのサイトではphp.ini
でcgi.fix_pathinfo=0
と指定すべきとしています。
例えばHow To Install Linux, nginx, MySQL, PHP (LEMP) stack on Ubuntu 14.04 | DigitalOceanではデフォルトのcgi.fix_pathinfo=1
が超危険と書かれています。
This is an extremely insecure setting because it tells PHP to attempt to execute the closest file it can find if a PHP file does not match exactly.
またUbuntuやDebianのNginxの設定ファイル/etc/nginx/sites-available/default
にも以下*1のように書かれており、やはりこの設定は必ずやらないといけないように思えます。
なぜこの設定が必要なのかを調べてみました。
cgi.fix_pathinfo=0とするようになった経緯
cgi.fix_pathinfo=0とするようになったのはFastCGIを使った際に生じるセキュリティ上の問題*2が原因です。
例えば、ファイルのアップロードが可能なウェブサイトがあったとします。このサイトはアップロードされたファイルを
http://example.com/uploads/photo.jpg
のようなURLで公開します。アップロードできるファイルの拡張子は.jpg
などに制限されています。ここで、
http://example.com/uploads/photo.jpg/foo.php
にアクセスがあった場合、FPMは/uploads/photo.jpg/
というディレクトリ内のfoo.php
を実行しようとします。もちろんそのようなファイルはないので404が返るはずですが、cgi.fix_pathinfo
が有効な場合(デフォルト有効)FPMは次に/uploads/photo.jpg
をPHPとして実行しようとします(/foo.php
はPATH_INFOとして扱われます)。
/uploads/
にはだれでもファイルをアップロードできるので、拡張子をjpgとしたPHPファイルをアップロードされた場合はかなり問題です。
そこで、cgi.fix_pathinfo
を無効にして前述の動作をさせないようにする対策が取られるようになりました。
security.limit_extensionsの導入
この問題はFPMが.php
以外のファイルをPHPとして実行しないようにすれば発生しません。
PHP :: Request #55181 :: Enhance security by limiting the script extensionでsecurity.limit_extensions
を導入してFPMが実行できる拡張子を制限することが提案され、2012年1月にリリースされたPHP 5.3.9からこの仕組みが導入されています。
security.limit_extensions
のデフォルト値は.php
です。したがって、PHP 5.3.9以降ではcgi.fix_pathinfo
を無効にする必要はありません。
まとめ
PHP 5.3.9以降ではcgi.fix_pathinfo=0
とする必要性はない。
例えば冒頭で紹介したサイトはUbuntu 14.04を対象としているのでcgi.fix_pathinfo=0
とする必要性はない。
安全側に倒してcgi.fix_pathinfo=0
としても問題ないが、cgi.fix_pathinfo
を有効にすると嬉しい事があるので有効にする流れになればいいと思う。どう嬉しいのかは別エントリで述べる。
参考
#642995 - Security issue with Nginx + PHP via FastCGI - Debian Bug report logs
http://cnedelcu.blogspot.jp/2010/05/nginx-php-via-fastcgi-important.html
*1:ちなみにこの文言はhttp://nginx.org/で配布されているNginxには書かれていません。
*2:2010年5月にnginx文件类型错误解析漏洞 - 80secで報告されたものです。