作成日:2020-01-31, 更新日:2020-01-31
基本
・パス・トラバーサル対策:ユーザーによる親階層のファイルへのアクセスを禁止したい
▼例えば・・・下記のようなディレクトリを削除させる処理
define('PATH_DOC', '/〇〇〇/〇〇〇');
$dir = PATH_DOC . '/' . $_POST['path'];
rmdir($dir);
▼「$_POST['path']」の値が・・・
・「hoge」などのディレクトリ名を期待→問題無い
・「../」などのような親を参照するような相対PATH→困る
対策1
手っ取り早くいくなら親を指定するような相対PATHの記述の「..」を認めなければいい
サンプル
・「..」だけのとき→消す
・「/..」or「../」→消す
・「hoge..xxx」とか変なファイル名→放置
・「.」「/」がエスケープされた「%2e」「%2f」→消す
function escPath($str){
if ( $str=='..' || $str=='%2e%2e' ) {
return '';
}
$ng_seed = array(
'/..', '%2f%2e%2e',
'../', '%2e%2e%2f',
);
return str_replace($ng_seed, '', $str);
}
define('PATH_DOC', '/〇〇〇/〇〇〇');
$dir = PATH_DOC . '/' . escPath($_POST['path']);
rmdir($dir);
※これだと親階層は削除されない。ただ対象PATHが見つからずに変なエラーになるかもしれない
対策2
・指定したディレクトリ配下じゃなければ認めない
サンプル
function chkPath($ori_path, $acs_path){
if ( strpos($acs_path, $ori_path) !== 0 ) {
// 指定外のパスになるならエラー
return false;
}
return true;
}
define('PATH_DOC', '/〇〇〇/〇〇〇');
$dir = realpath(PATH_DOC.'/'.$_POST['path']);
if ( !_p(PATH_DOC, $dir) ) {
// 処理中止
exit;
}
else {
// 処理続行
rmdir($dir);
}