どの$ _SERVER変数が安全ですか?


97

ユーザーが制御できるすべての変数、攻撃者も制御できるため、攻撃のソースになります。これは「汚染された」変数と呼ばれ、安全ではありません。

を使用すると$_SERVER、多くの変数を制御できます。PHP_SELFHTTP_USER_AGENTHTTP_X_FORWARDED_FORHTTP_ACCEPT_LANGUAGEおよび他の多くは、クライアントによって送信されたHTTPリクエストヘッダの一部です。

誰かが「安全なリスト」または汚染されていない$_SERVER変数のリストを知っていますか?


8
「安全」の定義方法によって異なります。値はすべてそのままで安全です。それは、何のためにそれらを使用するかにのみ依存します。
だます

6
この文脈では、Rookは「ユーザーはどのサーバー変数を偽装できないか」などと言っていると思いますREMOTE_ADDR
vcsjones 2011年

6
で始まるものHTTP_はすべてリクエストヘッダーであり、ブラウザまたはプロキシを介して設定できます。それらを他のユーザー入力と見なします。
datasage 2011年

3
@ bob-the-destroyer REMOTE_ADDRは、ApacheのTCPソケットから直接プルされます。この値は、3方向のハンドシェイクのため、インターネット上で偽装することはできません
ルーク

2
@ルーク:良い点。私は「なりすまし」について言及していると思いますが、実際の値を偽るのではなく、ipなりすまし自体の古い行為に傾倒していたのREMOTE_ADDRです。そして、それはこの質問の範囲外です。この値がどのように設定されているかについての洞察を得るために良いので、ありがとう。
bob-the-destroyer

回答:


147

「安全」な値や「安全でない」値などはありません。サーバーが制御する値とユーザーが制御する値だけがあり、値の取得元を認識する必要があるため、特定の目的で信頼できるかどうかを確認する必要があります。$_SERVER['HTTP_FOOBAR']たとえば、データベースに保存することは完全に安全ですが、私は間違いなくそうしませんeval

そのため、これらの値を3つのカテゴリーに分けましょう。

サーバー制御

これらの変数はサーバー環境によって設定され、サーバー構成に完全に依存します。

  • 'GATEWAY_INTERFACE'
  • 'SERVER_ADDR'
  • 'SERVER_SOFTWARE'
  • 'DOCUMENT_ROOT'
  • 'SERVER_ADMIN'
  • 'SERVER_SIGNATURE'

部分的にサーバー制御

これらの変数は、クライアントが送信した特定のリクエストに依存しますが、すべての無効な値はWebサーバーによって拒否され、スクリプトの呼び出しを開始させないため、限られた数の有効な値しか取ることができません。したがって、それらは信頼できると見なすことができます。

  • 'HTTPS'
  • 'REQUEST_TIME'
  • 'REMOTE_ADDR' *
  • 'REMOTE_HOST' *
  • 'REMOTE_PORT' *
  • 'SERVER_PROTOCOL'
  • 'HTTP_HOST'
  • 'SERVER_NAME'
  • 'SCRIPT_FILENAME'
  • 'SERVER_PORT'
  • 'SCRIPT_NAME'

*これらのREMOTE_値は、TCP / IPハンドシェイクによって検証されるように、クライアントの有効なアドレスであることが保証されています。これは、応答が送信されるアドレスです。REMOTE_HOSTただし、逆DNSルックアップに依存しているため、サーバーに対するDNS攻撃によってスプーフィングされる可能性があります(この場合は、とにかく大きな問題が発生します)。この値はプロキシである場合があります。これは、TCP / IPプロトコルの単純な現実であり、何も実行できません。

†Webサーバーがヘッダーに関係なく要求に応答する場合HOST、これも安全ではないと見なされます。$ _SERVER [“ HTTP_HOST”]の安全性を参照してくださいhttp://shiflett.org/blog/2006/mar/server-name-versus-http-host
も参照してください

‡参照https://bugs.php.net/bug.php?id=64457http://httpd.apache.org/docs/current/mod/core.html#usecanonicalphysicalport//httpd.apacheます。http。 org / docs / 2.4 / mod / core.html#comment_999

完全に任意のユーザー制御値

これらの値はまったくチェックされず、サーバー構成に依存しません。これらは、クライアントから送信される完全に任意の情報です。

  • 'argv''argc'(CLI呼び出しにのみ適用され、通常はWebサーバーには関係ありません)
  • 'REQUEST_METHOD' §
  • 'QUERY_STRING'
  • 'HTTP_ACCEPT'
  • 'HTTP_ACCEPT_CHARSET'
  • 'HTTP_ACCEPT_ENCODING'
  • 'HTTP_ACCEPT_LANGUAGE'
  • 'HTTP_CONNECTION'
  • 'HTTP_REFERER'
  • 'HTTP_USER_AGENT'
  • 'AUTH_TYPE'
  • 'PHP_AUTH_DIGEST'
  • 'PHP_AUTH_USER'
  • 'PHP_AUTH_PW'
  • 'PATH_INFO'
  • 'ORIG_PATH_INFO'
  • 'REQUEST_URI' (汚染されたデータが含まれている可能性があります)
  • 'PHP_SELF' (汚染されたデータが含まれている可能性があります)
  • 'PATH_TRANSLATED'
  • その他の'HTTP_'

§Web サーバーが特定のリクエストメソッドのみを許可している限り、信頼できると見なされます。

authentication認証が完全にWebサーバーによって処理される場合、信頼できると見なされます。

スーパーグローバル$_SERVERには、いくつかの環境変数も含まれています。これらが「安全」であるかどうかは、それらの定義方法(および場所)に依存します。完全にサーバー制御から完全にユーザー制御までさまざまです。


3
@Rookしかし、私が言ったように、それはあなたがそれどのように使用するかに完全に依存します。値自体は安全でも安全でもありません。値の用途によって異なります。悪意のあるユーザーから送信されたデータでさえ、セキュリティを危険にさらす可能性のあるデータを使用していない限り、完全に安全です。
だます

2
@Rook:「安全な」というあなたの考えでは、この質問は特に恣意的に見えるようになります。これは、あいまいな拡張機能またはカスタムバージョンのPHPに完全に関連付けられているためです。あなたは「ヒップからのシュート」アプローチをとるべきではないと言っていますが、実際の回答では、これらの値がどのように設定されているかを知るために、少なくともPHPのソースコードに精通している必要があります。PHP開発者にメールを送るのは、答えを見つけるためのより良いアプローチではないでしょうか?
bob-the-destroyer

2
@ルーク:誤解。だますがほのめかしたように、「どんな目的でも安全」。ほのめかしたように、あなたの目的は不明であり$_SERVER、ファイルの提供方法に応じて、文書化されていない他のいくつかの値があります。私の意見では、文書化されたものは本当の出典を明確にしていません。そうでなければ、私はあなたがこの質問をすることはないと思います。使用できるリストを入手できてうれしいです。ただし、バグレポートの提出(バグサイトが修正された場合)、ドキュメントのメンテナーへのメール送信、またはドキュメントの更新(リンクを知っている場合)をお勧めします。この情報を知ることはコミュニティに利益をもたらすでしょう。
bob-the-destroyer

3
SERVER_NAME必ずしもサーバーによって制御されるわけではありません。ゲートウェイと設定によっては、複製される可能性があるHTTP_HOSTため、同じ注意が必要です。
bobince

1
@deceze @Rook SERVER_PORTその小さな十字架は必要ですか?bugs.php.net/bug.php?id=64457
デヤンMarjanović

12

PHPでは、で$_SERVER始まるすべての変数HTTP_がユーザーの影響を受ける可能性があります。たとえば、HTTPリクエストで$_SERVER['HTTP_REINERS']HTTPヘッダーREINERSを任意の値に設定することで、変数を汚染することができます。


「任意」について; 形式に準拠しているため、完全なものではありません。たとえば、$_SERVER['HTTP_REINERS'] ほとんどのsapiでは、改行文字を含めることはできません。
ペーチェリエ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.