1

$_SERVER['REQUEST_URI']使用包含文件是否存在任何安全风险?你能../../..以某种方式通过请求uri吗?

我在想的是这样的:

<?php
$path = $_SERVER['REQUEST_URI'];
$path = preg_replace('~\\.html?$~', '.php', $path);
include $path;
?>

这应该用“.htm”或“.html” URI 替换“.php”路径并呈现它们。但我担心这里的安全。

4

4 回答 4

4

$_SERVER['REQUEST_URI']包含请求的 URI 路径和查询字符串,因为它出现在HTTP 请求行中。所以当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.

所以这实际上是一个本地文件包含漏洞

现在要解决这个问题,使用您 chowey 提出的方法需要某个根目录是一个很好的改进。但你实际上需要在它前面加上$basedir

$path = realpath($basedir . $_SERVER['REQUEST_URI_PATH']);
if ($path && strpos($path, $basedir) === 0) {
    include $path;
}

该解决方案提供了几个承诺:

  • $path是现有文件的有效解析路径,或者false;
  • $basedir仅当前缀路径为.时才会包含该文件$path

但是,这可能仍然允许访问使用某种其他类型的访问控制保护的文件,例如 Apache 的 mod_authz_host 模块提供的访问控制。

于 2013-04-21T07:51:22.477 回答
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扩展名限制。

于 2013-09-18T16:55:18.180 回答
0

在检查基本路径之前,确实不要相信 $_SERVER['REQUEST_URI'] 。

并且不要制作从路径中删除 ../ 的过滤器,如果攻击者了解过滤器过程,他们可以制作一种新的注入方式。

于 2013-04-27T12:13:04.347 回答
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目录中。

于 2013-04-20T23:31:16.653 回答