29

问候,我希望让我的小程序安全,以便潜在的恶意用户无法查看服务器上的敏感文件。

    $path = "/home/gsmcms/public_html/central/app/webroot/{$_GET['file']}";


    if(file_exists($path)) {
        echo file_get_contents($path);
    } else {
        header('HTTP/1.1 404 Not Found');
    }

在我的脑海中,我知道诸如“../../../../../../etc/passwd”之类的输入会很麻烦,但想知道我应该期待哪些其他恶意输入以及如何防止他们。

4

9 回答 9

37

realpath()将允许您将任何可能包含相对信息的路径转换为绝对路径......然后您可以确保该路径位于您要允许下载的某个子目录下。

于 2009-12-16T00:11:21.200 回答
14

使用basename而不是试图预测用户可能提供的所有不安全路径。

于 2009-12-16T00:06:24.480 回答
9

OP的解决方案:

$baseDir = "/home/gsmcms/public_html/central/app/webroot/"; 
$path = realpath($baseDir . $_GET['file']); 

// if baseDir isn't at the front 0==strpos, most likely hacking attempt 
if(strpos($path, $baseDir) !== 0) { 
   die('Invalid Path'); 
} elseif(file_exists($path)) { 
   echo file_get_contents($path); 
} else { 
   header('HTTP/1.1 404 Not Found'); 
   echo "The requested file could not be found"; 
} 
于 2014-10-30T21:48:26.350 回答
6

如果可以,请使用允许文件数组之类的白名单并检查输入:如果用户询问的文件不在该列表中,则拒绝该请求。

于 2009-12-16T00:14:25.517 回答
5

这里还有一个额外的重大安全风险。此脚本将文件源注入输出流,无需任何服务器端处理。这意味着您的任何可访问文件的所有源代码都将泄露到互联网上。

于 2009-12-16T13:31:08.223 回答
4

即使您使用的是 realpath,您仍然应该在使用它之前去掉所有的“..”。否则,攻击者可以暴力读取您的服务器的整个目录结构,例如“valid_folder/../../test_if_this_folder_name_exists/valid_folder” - 如果应用程序接受此路径,则攻击者知道该文件夹存在。

于 2016-03-08T11:48:33.573 回答
0

另一种方法:

$path = "/app/webroot/{$_GET['file']}";
$realTarget = realpath($path);

if( strtolower($path) !== strtolower($realTarget) ) {
    // invalid path!
}
// life goes on
于 2021-03-16T19:30:18.363 回答
0

我认为这是 PHP7 的最佳答案。

这只会让人们看到他们拥有绝对路径的文件。

通过使所有失败条件报告相同,它不会让人们在指定路径之外寻找有效文件名。

$base_dir = $temp_path;
$path = "";
if(isset($_GET['filename'])) {
    $path = realpath($base_dir.$_GET['filename']);
    //realpath returns false if the file doesnt exist
    if(!$path ||
    //dont look outside temp path 
        substr($path, 0, strlen($base_dir)) != $base_dir){
            header('HTTP/1.1 404 Not Found'); 
            echo "The requested file could not be found";
            die;
    }
}
于 2021-03-20T10:23:01.043 回答
-1

剥离全部/. /..或\。\.. 并转换为所有正斜杠,因为不同的环境将接受正斜杠。这应该为路径输入提供一个相当安全的过滤器。在您的代码中,您应该将其与您不想访问的父目录进行比较,以防万一。

 $path = realpath(implode('/', array_map(function($value) {return trim($value, '.');}, explode('/', str_replace('\\', '/', $path)))));  
于 2017-03-05T19:22:52.783 回答