web-dev-qa-db-ja.com

PHPオプション 'cgi.fix_pathinfo'はNginx + PHP-FPMで本当に危険ですか?

alotoftalkingcgi.fix_pathinfoに関連するセキュリティ問題についてありました= PHPオプションはNginxで使用されます(通常、PHP-FPM、高速CGI)。

その結果、デフォルトのnginx設定ファイルは次のように言っていました:

# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

しかし、今では、「公式」のNginx wiki それを述べています PATH_INFOは、上記のPHPオプションを無効にすることなく、正しく処理できます。それで、何ですか?

ご質問

  • cgi.fix_pathinfoの機能を明確に説明できますか? ( 公式ドキュメントは言うだけです :「PATH_INFOの詳細については、CGI仕様を参照してください」)
  • PHPは実際にこれらのPATH_INFOおよびSCRIPT_FILENAME変数で何をしますか?
  • Nginxではなぜ、どのように危険なのでしょうか。 (詳細例)
  • 問題はこれらのプログラムの最近のバージョンでもまだ存在しますか?
  • Apacheは脆弱ですか?

各ステップで問題を理解しようとしています。たとえば、なぜphp-fpm Unixソケットを使用するのか理解できません 回避できました この問題。

55
Totor

TL; DR-修正(必要ない場合もあります)は非常に簡単で、この回答の最後にあります。

特定の質問に取り組みますが、PATH_INFOとは何かを誤解しているため、質問自体が少し間違っています。

  • 最初の質問は「このパス情報ビジネスとは何ですか?」

  • 次の質問は、「PHPはPATH_INFOSCRIPT_FILENAMEが何であるかをどのように判断するのですか?」

    • PHPの以前のバージョンは素朴で、技術的にはPATH_INFOもサポートしていなかったため、PATH_INFOSCRIPT_FILENAMEに変更されました。ケース。 PHPをテストするのに十分古いバージョンはありませんが、シバン全体としてSCRIPT_FILENAMEを認識したと思います: "/path/to/script.php/THIS/IS/PATH/上記の例のINFO "(通常はdocrootが前に付けられています)。
    • Cgi.fix_pathinfoが有効になっていると、PHPは上記の例の「/ THIS/IS/PATH/INFO」を正しく検出してPATH_INFOに入れ、SCRIPT_FILENAMEが指す部分だけを取得します。要求されるスクリプト(もちろんdocrootが前に付けられます)。
    • 注:PHPが実際にPATH_INFOをサポートするようになったとき、古い動作に依存するスクリプトを実行しているユーザーが新しいPHPバージョンを実行できるように、新機能の構成設定を追加する必要がありました。そのため、設定スイッチさえあります。最初から組み込まれているはずです(「危険な」動作を伴う)。
  • しかし、PHPはどのようにしてスクリプトのどの部分とそのパス情報を知るのでしょうか。 URIが次のような場合:

    http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo

    • これは、環境によっては複雑な問題になる場合があります。 PHPで発生するのは、サーバーのdocrootの下にある何にも対応しないURIパスの最初の部分を見つけることです。この例では、サーバーに「/docroot/path/to/script.php/THIS」がないことがわかりますが、「/ docroot/path/to/script.php」があるので、 SCRIPT_FILENAMEが決定され、PATH_INFOが残りを取得します。
    • したがって、Nginxのドキュメントと HrvojeŠpoljarの回答 (このような明確な例に煩わされることはできません)で詳細に説明されている危険の良い例がさらに明確になります。Hrvojeの例( " http://example.com/foo.jpg/nonexistent.php ")、PHPはdocroot "/foo.jpg"上のファイルを表示しますが、呼び出されるものは何も表示しません"/foo.jpg/nonexistent.php"なので、SCRIPT_FILENAMEは "/foo.jpg"(これもdocrootで始まる)を取得し、PATH_INFOは "/nonexistent.php"を取得します。
  • なぜ、どのように危険なのかが明確になりました。

    • Webサーバーに問題はありません。単にURIをPHPにプロキシしているだけです。これにより、 "foo.jpg"に実際にPHPコンテンツが含まれていることが無邪気に検出され、実行されます(これで実行されました)。これは[〜#〜] [〜#〜]ではなく、Nginx自体に固有のものです。
  • [〜#〜]実際[〜#〜]の問題は、信頼できないコンテンツをサニタイズせずにどこかにアップロードさせ、他の任意のリクエストを許可することです同じ場所。PHPは可能な場合に喜んで実行します。
  • NginxとApacheは、このトリックを使用してリクエストを防止するように構築または構成できます。これを行う方法の例は ser2372674の回答 に含まれています。 このブログ記事 は問題をうまく説明していますが、適切な解決策がありません。

  • ただし、最良の解決策は、PHP-FPMが正しく構成されていることを確認することです。これにより、ファイルが「.php」で終わっていない限り、ファイルが実行されることはありません。 PHP-FPMの最近のバージョン(〜5.3.9 +?)にはこれがデフォルトとして設定されているので、この危険はそれほど問題にはなりません。

ソリューション

PHP-FPMの最新バージョン(〜5.3.9 +?)を使用している場合、以下の安全な動作はすでにデフォルトなので、何もする必要はありません。

それ以外の場合は、php-fpmのwww.confファイルを探します(多分/etc/php-fpm.d/www.conf、システムによって異なります)。これがあることを確認してください:

security.limit_extensions = .php

繰り返しますが、最近では多くの場所でそれがデフォルトになっています。

これは、攻撃者が「.php」ファイルをWordPressアップロードフォルダにアップロードし、同じ手法を使用して実行することを妨げるものではないことに注意してください。それでも、アプリケーションのセキュリティを確保する必要があります。

84
user109322

基本的に、これがなければ、 'foo.jpg'のような名前のPHPコードを含むファイルをWebサーバーにアップロードできます。次に http://domain.tld/foo.jpg/nonexistent.php のように要求すると、Webサーバースタックは誤ってああ言うでしょう。これはPHPです。これを処理する必要があります。foo.jpg/ nonexistent.phpが見つからないため、foo.jpgにフォールバックし、phpコードとしてfoo.jpgを処理します。それはシステムを非常に簡単な侵入に開放するので危険です。たとえば、画像のアップロードを許可するWebアプリケーションは、バックドアをアップロードするためのツールになります。

Php-fpmをunixソケットで使用して回避することについて。 IMOそれは問題を解決しません。

14
Hrvoje Špoljar

Nginx wiki でセキュリティ対策として

if (!-f $document_root$fastcgi_script_name) {
    return 404;
}

ロケーションブロックに含まれています。他のチュートリアルでは

try_files $uri =404;

nginx wikiによれば、同じように動作するはずですが、問題が発生する可能性があります。これらのオプションを使用すると、cgi.fix_pathinfo=1はもう問題にはなりません。詳細は here を参照してください。

3
user2372674