作成日: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); }