使用$_SERVER['REQUEST_URI']
包含文件是否涉及任何安全风险?你能不能以某种方式通过../../..
通过请求uri?
我在想的是这样的:
<?php
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace('~\\.html?$~', '.php', $path);
include $path;
?>
这应该替换“.php”路径的“.htm”或“.html”URI并渲染它们。但我担心这里的安全。
答案 0 :(得分:3)
$_SERVER['REQUEST_URI']
包含HTTP request line中显示的请求的URI路径和查询字符串。因此,当请求http://example.com/foo/bar?baz=quux
并且服务器将请求传递给脚本文件/request_handler.php
时,$_SERVER['REQUEST_URI']
仍然是/foo/bar?baz=quux
。我使用mod_rewrite将任何请求映射到request_handler.php
,如下所示:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /request_handler.php
因此,为了正确起见,在文件系统路径中使用$_SERVER['REQUEST_URI']
之前,您需要删除查询字符串。您可以使用parse_url
执行此操作:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
但由于此值直接来自HTTP请求行而没有先前的路径解析,因此它可能仍包含符号路径段,如..
。
但是,路径遍历甚至不是必需的,因为请求的URI路径已经是绝对路径引用,请求http://example.com/etc/passwd
应该包含/etc/passwd
。
所以这实际上是local file inclusion vulnerability。
现在要解决这个问题,要求使用你所提出的method的某个根目录是一个很好的改进。但实际上你需要用$basedir
:
$path = realpath($basedir . $_SERVER['REQUEST_URI_PATH']);
if ($path && strpos($path, $basedir) === 0) {
include $path;
}
这个解决方案提供了几个承诺:
$path
是现有文件的有效解析路径,或false
; $basedir
是$path
的前缀路径时才会包含该文件。但是,这可能仍允许访问使用其他类型的access control like the one provided by Apache’s mod_authz_host module保护的文件。
答案 1 :(得分:0)
这实际上并没有回答这个问题......
请注意,您可以确保请求uri指向当前工作目录中的实际有效文件路径。您可以使用realpath
函数来规范化路径。
以下代码可以解决问题:
<?php
$basedir = getcwd();
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace('~\\.html?$~', '.php', $path);
$path = realpath($path);
if ($path && strpos($path, $basedir) === 0) {
include $path;
} else {
return false;
}
?>
我在这里使用strpos
来验证$path
是否以$basepath
开头。由于realpath
将删除任何../../..
有趣的商家,因此应安全地将您置于$basepath
目录中。
答案 2 :(得分:0)
在检查基路径之前,确实不信任$ _SERVER ['REQUEST_URI']。
并且不要制作一个过滤器,从路径中移除../攻击者如果能够理解过滤器过程,就可以采用新的方式进行注入。
答案 3 :(得分:0)
我有同样的问题,并选择以 Gumbo的答案为基础做以下事情:
$_SERVER['REQUEST_URI_PATH'] = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path = realpath(FOLDER_ROOT . $_SERVER['REQUEST_URI_PATH']);
$directory_white_list_array = array('/safe_folder1', '/safe_folder1/safe_folder2');
if ($path && strpos($path, FOLDER_ROOT) === 0 && (in_array(dirname($path), $directory_white_list_array) && ('php' == pathinfo($path, PATHINFO_EXTENSION)))) {
include $path;
}else{
require_once FOLDER_ROOT."/miscellaneous_functions/navigation_error.php";
navigation_error('1');
}
要点: 添加了目录白名单和.php扩展名限制。