100%信頼できますか$_SERVER[]
私が行うようにサニタイズする必要のない安全なデータソースになる$_GET[]
および$_POST[]
?
これは、スタックオーバーフローに関する私の質問の1つから取られたものです どの$ _SERVER変数が安全ですか?
これらの変数はサーバー環境によって設定され、サーバー構成に完全に依存します。
'GATEWAY_INTERFACE'
'SERVER_ADDR'
'SERVER_SOFTWARE'
'DOCUMENT_ROOT'
'SERVER_ADMIN'
'SERVER_SIGNATURE'
これらの変数は、クライアントが送信した特定のリクエストに依存しますが、すべての無効な値はWebサーバーによって拒否され、スクリプトの呼び出しを開始しないため、限られた数の有効な値しか取ることができません。したがって、それらはreliableと見なすことができます。
'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
ヘッダーに関係なくany要求に応答する場合、これも安全ではないと見なされます。 $ _ SERVER [“ HTTP_Host”]?は安全ですか? を参照してください。
http://shiflett.org/blog/2006/mar/server-name-versus-http-Host も参照してください。
これらの値はまったくチェックされず、サーバー構成に依存しません。これらは、クライアントから送信される完全に任意の情報です。
'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'
(汚染されたデータ、つまり/index.php/evilstringが含まれている可能性があります)'PATH_TRANSLATED'
'HTTP_'
値the Webサーバーが特定の要求メソッドのみを許可している限り、信頼できると見なされます。
§認証がWebサーバーによって完全に処理される場合、reliableと見なされます。
スーパーグローバル$_SERVER
には、いくつかの環境変数も含まれています。これらが「安全」であるかどうかは、それらの定義方法(および場所)に依存します。完全にサーバー制御から完全にユーザー制御までさまざまです。
$ _GET []や$ _POST []のようにサニタイズする必要のない安全なデータソースとして、$ _ SERVER []を100%信頼できますか?
あなたの質問はすぐに失敗を示します。入力のすべてのソースはサニタイズする必要があります。入力は、ユーザーが直接制御できるチャネルと見なされるだけでなく、アプリケーションの外部にあるすべてのデータソースと見なされます。
このように考えると、アプリケーションにはデータを取得する2つの方法があります。アプリケーションでハードコードされた情報と入力です。同じシステム上の別のプログラムによって生成されたとしても、それはあなたのプログラムへの入力のままです。
一般的なイディオム_Filter-In, Escape-Out
_は、ユーザー入力だけでなく、アプリケーションに出入りするあらゆるものに適用されます。
したがって、それが_$_SERVER
_内にある場合、それは[〜#〜] must [〜#〜]フィルタリング/サニタイズされる必要があります。アプリケーションでハードコーディングされていないものに依存することはできません。
何でこれが大切ですか?ユーザーからのすべての入力をフィルタリングし、データベースからのデータを信頼するとします。フィルタリングの穴を利用できれば、信頼できるデータを注入できます。これにより、2次のXSSまたはSQLiが発生する可能性があります。しかし、アプリケーションに含まれるすべてのものをフィルタリングすると、アプリケーションがどこから来た場合でも、どこから来ても安全です。
つまり、_$_SERVER
_、_$_GET
_、_$_POST
_、_$_COOKIE
_、_$_REQUEST
_、_$_ENV
_、_$argc
_、_$argv
_、データベース、ファイルシステム(バージョン管理コードを除く)などから...
まったくばかげた質問ではありません!
$ SERVER変数の多く(すべてではない)がユーザーのブラウザーから渡されます(またはユーザーの影響を受ける可能性があります)。たとえば、QUERY_STRING、REQUEST_URI、およびすべてのHTTP_ *変数です。
REMOTE_ADDR変数でさえ、生のソケットを使用してスプーフィングされる可能性があります(ただし、私が知る限り、有効なIPを使用している場合のみです)。
私は良い政策の問題としてそれらすべてを逃れるでしょう。
「データの安全なソース」などはありません。他のデータに渡すときは、データが正しい形式であることを常に確認する必要があります。
アポストロフィ( ')で区切られた文字列[1]内でSQLに出力する場合は、アポストロフィ(または文字列を区切る可能性のあるその他の文字)をエスケープする必要があります。 Javascriptアポストロフィで区切られたstring [2]に出力する場合は、HTMLとアポストロフィの両方をエスケープする必要があります。それはすべて、出力先に依存します。完全に安全な文字列は、悪意のある方法でなくても、ターゲットスクリプトを破壊する可能性があります。 (ただし、壊れる可能性がある場合は、悪用されることもあります。)
[1]例:$db->query("SELECT * FROM users WHERE name = '$username'");
[2]例:<script>alert('Hi <?php echo $username;?>');</script>
私のブログでこのエスケープについて話しましたが、私の投稿は特にXSSについてですが、同じ原則がここでも当てはまると思います: XSSとは何ですか、またWebサイトを保護する方法 。
PHP自体が既に特定の形式を強制していることを知らない限り、ほとんど確実ではないので、すべてを安全でないと見なすことができます。IPアドレスは通常xxxx形式で提供されますが、 IPv6の場合はx:x:x:x:x:x:x:xです。IPv6パケットのIPv4宛先の場合は0:0:0:0:0:ffff:xxxxです。これに気付いていない場合は、それはいくつかの非常に興味深いバグにつながるかもしれません。
これで、IPアドレスにアポストロフィが含まれることはありません。リモートアドレスを使用する前に$ _SERVER ["HTTP_X_FORWARDED_FOR"]ヘッダーをチェックする人がいます。ヘッダーが正しく設定されている限り(@GBCの応答へのコメントで@Ladadadadaが指摘しているように)、これはすばらしいことですが、それもまたなりすましの可能性があります。次に、他の人がデータベースに保存したデータを使用すると、悪意のあるものを取り戻す可能性があります...つまり、結局、決して入力を信頼しないでください。一度忘れるよりも安全にしておく方がいいです。