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


51

なされてきたたくさんにセキュリティ上の問題に対して約nginxの(通常はPHP-FPM、ファストCGI)で使用するPHPオプション。 cgi.fix_pathinfo

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

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

ただし、現在、「公式」のNginx wiki では、上記のPHPオプションを無効にせずにPATH_INFOを正しく処理できると述べています。だから何?

ご質問

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

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


1
あなたはPATH_INFOとPATH_TRANSLATEDの違いを理解することにより、独自の質問に答えるかもしれません:blogs.msdn.com/b/david.wang/archive/2005/08/04/...
ジョバンニTirloni

回答:


79

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

特定の質問に対処しようとしますが、PATH_INFOが何であるかを誤解すると、質問自体が少し間違っています。

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

  • 次の質問は、「PHPはどのように何PATH_INFOを決定SCRIPT_FILENAMEするのですか?」

    • PHPの以前のバージョンでは、ナイーブだった、技術的にもサポートしていませんでしたPATH_INFOどのようなことになったので、PATH_INFO上にマングドたSCRIPT_FILENAMEその、はい、多くの場合、壊れています。テストするのに十分な古いバージョンのPHPはありませんがSCRIPT_FILENAME、上記の例の「/path/to/script.php/THIS/IS/PATH/INFO」(接頭辞付き)通常どおりdocroot)。
    • cgi.fix_pathinfoを有効にすると、PHPは上記の例の「/ THIS / IS / PATH / INFO」を正しく検出し、要求されているスクリプト(もちろんdocrootで始まる)を指す部分だけPATH_INFOSCRIPT_FILENAME取得します。
    • 注: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にプロキシしているだけです。PHPは「foo.jpg」に実際にPHPコンテンツが含まれていることを無邪気に検出するので、実行します(これで、pwned!)これは、Nginx自体に固有のものではありません
  • REAL問題は、あなたが信頼できないコンテンツが消毒せずにどこかにアップロードすると、あなたはそれができるPHPは喜んで実行し、同じ場所に他の任意の要求を許可しましょうということです。
  • NginxとApacheは、このトリックを使用してリクエストを防ぐように構築または構成することができ、user2372674の回答を含む、その方法の例がたくさんありますこのブログ記事では問題をうまく説明していますが、正しい解決策がありません。

  • ただし、最良の解決策は、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のアップロードフォルダーにアップロードし、同じ手法を使用して実行することを妨げないことに注意してください。あなたはまだあなたのアプリケーションのために良いセキュリティを持っている必要があります。


5
素敵な答え!明確にするために、もしあなたが言うように、PHPが何SCRIPT_FILENAMEであるかを決定したら、なぜfastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;私のnginxconfに行がありますか?SCRIPT_FILENAMEそれ自体の価値を発見するPHPの努力を無効にしますか?
トーター

の値を取得する関数はありsecurity.limit_extensionsますか?私が試したphpinfo()ini_get(security.limit_extensions)と、ini_get_all()いない成功を収めました。
elbowlobstercowstand

PHP-FPMの最近のバージョン(〜5.3.9 +?)がデフォルトとしてこれを持っている場合、どうしてphp7.1が必要なのですか?それともこの記事は間違っていますか?
エフゲニーアファナシエフ

14

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

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


私が提供したリンクで読むことができるものだけを繰り返します。あなたは本当のメカニズムを説明しません。あなたの答えには、付加価値が必要です。
トーター14

6
それは本当かもしれませんが、あなたのタイトルには質問があり、その質問への回答は私の回答にあります。明示的に必要な場合; はい、それは危険です。すごく危ない。
フルボイェショポルジャー14

1 /私の答えはそのタイトルに限定されません:体を持っています。2 / user109322が間違っていることを証明しました。デフォルトのconf は安全であるため、使用される値危険でcgi.fix_pathinfoはありませんphp-fpm.php拡張子を持つファイルのみを実行します)。
トーター

2

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

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

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

try_files $uri =404;

同じことをするはずですが、Nginx wikiによると問題を引き起こす可能性があります。これらのオプションを使用すると、cgi.fix_pathinfo=1もう問題になりません。詳細については、こちらをご覧ください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.