上へ

ディレクトリトラバーサル

ディレクトリトラバーサルは、「../」を使ってディレクトリの上の階層に移動できるため、ウェブサーバのトップページの外側にあるファイルにも接続することが可能です。そのため、UNIX系のオペレーティングシステムではpasswdファイルなどの内容が漏洩します。

攻撃される場所

ディレクトリトラバーサルはリクエストをPHPファイルに記述した$_POSTや$_GETなどの変数で受け取ることによって発生します。下記コードを記述したPHPファイルを例えばドキュメントルートに設置した場合、「../」を使ってpasswdファイルまでの位置を指定したパスをフォームに入力することで、passwdファイルの中身が出力されてしまいます。$_GETを使った変数では、URLの最後尾に「?attackFilePath=passwdファイルへのパス」という形式で送信することでpasswdファイルの中身が出力されてしまいます。尚、POST送信では「「?attackFilePath=」の部分は不要です。

// HTML
<form action="" method="post">
<input type="text" size="40" name="AttackFilePath" value="" />
<input type="submit" value="クリック" />
</form>
// PHP
$file='/ドキュメントルート/'.$_POST['AttackFilePath'];
readfile($file);

対処法

ini_set()で制限する

構文は「ini_set('open_basedir', '/制限したいパス/');」です。
ドキュメントルートより上の階層へアクセスさせないためには、ドキュメントルートまでのパスを指定します。例えばApacheのルートディレクトリでは「/var/www/html/」といった感じになります。
ini_set()のopen_basedirはPHPからアクセスできるファイルを指定したディレクトリツリーに限定することができます。しかしPHP5.2.6とPHP5.3.4以降以外のバージョンでは、この制限をプレフィックスとして取り扱っており、例えば「/dir/inc」などとしてもアクセスができます。もしこれをディレクトリに限定する場合は、末尾にスラッシュを付けます。(プレフィックスはPHPの古いバージョンで採用されていたものであり、PHP7などではディレクトリ名で制限指定します。)

ホワイトリストで制限する

if(isset($_POST["AttackFilePath"]) === true && $_POST["AttackFilePath"] !==''){
if(!in_array($_POST["attackFilePath"], array(読込OKファイルパス1, 読込OKファイルパス2 [,・・・]))){
exit;
}
$file='/ドキュメントルート/'.$_POST['AttackFilePath'];
readfile($file);
}

上記コードは配列で指定されたファイル内に、$_POST["AttackFilePath"]が無い場合にexitで処理を終了しています。また、$_GETで記述している場合は、$_POSTを$_GETにします。

その他

接続を許可するファイルが多いケースでは、ブラックリストで制限します。しかし、基本的にはホワイトリストで対応する方が確実です。また、不正文字を取り除くという方法もありますが、こちらは想定していないディレクトリへの接続を防ぐメリットがありますが、階層構造を扱うことが出来ません。そのため、臨機応変に処理対応を変更する方が合理的です。