我想确保通过查询字符串设置的文件路径不会超出所需的子目录。现在,我正在检查:
/
”开头,以防止用户提供绝对路径。..
”,以防止用户提供超出所需子目录的路径。:
”,以防止使用网址(即“http://
”,“ftp://
”等。我是否应该在Windows服务器上运行此脚本(不太可能),这也会阻止以驱动器说明符开头的绝对路径(即“C:\
”)。注意:我知道冒号是Unix文件名中的有效字符,但我永远不会在文件名中使用它。\
”开头。为了防止我改变主意在Windows服务器上运行,这可以防止指定Windows网络路径(即“\\someserver\someshare
”)。同样,我知道反斜杠是一个有效的Unix文件名字符,但我也不会在任何文件名中使用它。这些检查是否足够?
背景
我有一个PHP脚本,它(通过查询字符串)获取要显示给用户的示例源文件的路径。所以我可能会给他们一个像“view_sample.php?path=accounting_app/report_view.php
”或“view_sample.php?path=ajax_demo/get_info.js
”这样的链接。
脚本看起来基本上是这样的:
$path = $_GET['path'];
if(path_is_valid($path) && is_file("sample/$path"))
{
header('Content-Type: text/plain');
readfile("sample/$path");
}
我担心恶意用户会看到该网址,并尝试执行“view_sample.php?path=../../database/connection_info.php
”之类的操作,并获取对“sample”目录中不的文件的访问权限。
我上面定义的四个检查(将在path_is_valid()
函数中实现)是否足以锁定恶意用户? (另外,我认为支票1,3和4基本上是不相关的,因为我在前面设置相对路径,但是如果我不这样做,那么支票就足够了吗?)
答案 0 :(得分:10)
呼叫
$path = realpath("sample/$path");
然后检查生成的路径是否以您期望的目录开头。
答案 1 :(得分:6)
<?php
// Current path information
$path = $_GET['path'];
$vroot = "sample";
// Validate that the $path is a subfolder of $vroot
$vroot = realpath($vroot);
if(substr(realpath($path), 0, strlen($vroot)) != $vroot or !is_dir($path)) {lid!
exit("Invalid path");
} else {
echo "Ah, everything is alright!";
}
?>
答案 2 :(得分:0)
realpath的使用不应改变路径,因此我以下列方式使用它:
function checkPath($pathToCheck) {
global $basepath;
$fullpath = $basepath.'/'.$pathToCheck;
if ($fullpath==realpath($fullpath) && is_dir($fullpath)) {
return $fullpath;
} else {
error_die('path not allowed: '.htmlentities($pathToCheck));
}
}