にまたがるファイルシステム ファイルをどのように使用する場合でも、どこかにファイル名を指定する必要があります。多くの場合、ファイル名は fopen() 関数のパラメータとして使用され、他の関数はそれが返すハンドルを呼び出します。ファイル名 抜け穴が発生するのは、 この場合、攻撃者はパスやファイル名の先頭部分と末尾部分を操作できないため、攻撃の可能性は限定されます。ただし、一部の攻撃では NULL (URL では %00 として表される) を使用して文字列を終了し、ファイル拡張子の制限を回避する場合があることに注意してください。この場合、最も危険な攻撃方法は、複数の ../ を使用して上位レベルのディレクトリにアクセスし、ファイル システムのスパニングを実現することです。たとえば、filename の値が次のように指定されているとします。
http://www.php.cn/ ... どちらでもない/パス/への/ファイル
多くの攻撃の場合と同様、文字列の作成時に汚染されたデータを使用すると、攻撃者に文字列を変更する機会が与えられ、アプリケーションが意図しない動作をすることになります。フィルタリングされたデータのみを使用して動的文字列を作成する習慣を身につければ、馴染みのない脆弱性を含む多くの種類の脆弱性を防ぐことができます。
fopen() によって呼び出されるファイル名の先頭の静的部分は /path/to であるため、上記の攻撃には必要以上に上向きのディレクトリの交差が含まれます。攻撃者は攻撃を開始する前にソース コードを表示できないため、一般的な戦略は ../ 文字列を何度も繰り返すことです。 ../ 文字列を何度使用しても上記の攻撃効果は破壊されないため、攻撃者がディレクトリの深さを推測する必要はありません。
fopen() 呼び出しを意図しない方法で動作させる上記の攻撃では、簡略化され、以下と同等になります:
<?php
$handle = fopen('/path/to/myfile.txt', 'r');
?>
多くの開発者は、問題に気づいた後、または攻撃を受けた後、場合によっては最初にデータを確認せずに、悪意のある可能性のあるデータを修正しようとするという間違いを犯します。第 1 章で述べたように、最良のアプローチは、フィルタリングをチェック プロセスとして考え、設定したルールに従うことをユーザーに強制することです。たとえば、正当なファイル名に文字のみが含まれている場合、次のコードはこの制限を強制できます。 このデータは PHP 関数でのみ使用され、リモート システムには送信されないため、ファイル名の値をエスケープする必要はありません。 Basename() 関数は、不要なパスが存在するかどうかを確認する場合に非常に役立ちます。 このプロセスは、ファイル名に文字のみを許可するよりも安全性が低くなりますが、そこまで厳格になる可能性は低いです。徹底した予防プロセスをより効果的に行うには、特に正規表現を使用してコードの正当性をチェックする場合 (関数 ctype_alpha( を使用する代わりに)、上記の 2 つの方法を組み合わせることです。 ))。
ファイル名の末尾全体がフィルターされていないデータで構成されている場合、高リスクの脆弱性が発生します:
<?php $handle = fopen("/path/to/{$_GET['filename']}.txt", 'r'); ?>
攻撃者に柔軟性を与えるということは、脆弱性が増えることを意味します。この例では、ファイル拡張子は $_GET['filename'] の一部であるため、攻撃者はパスやファイル拡張子に関係なく、ファイル名パラメーターを操作してファイル システム内の任意のファイルを指すことができます。 WEB サーバーがファイルの読み取り権限を取得すると、攻撃者が指定したファイルに処理が送られます。
パスの先頭部分で汚染されたデータが使用されている場合、この種の脆弱性はさらに大きくなります。これも次のセクションの主題です。