在PHP中清理文件路径

Sea*_*ney 27 php security sanitization

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

    $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');
    }
Run Code Online (Sandbox Code Playgroud)

在我的脑海中,我知道像'../../../../../../etc/passwd'这样的输入会有麻烦,但想知道我应该期待什么其他有意义的输入以及如何防止他们.

Ber*_*amb 36

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

  • 这是我的最终解决方案:$ baseDir ="/ home/gsmcms/public_html/central/app/webroot /"; $ path = realpath($ baseDir.$ _GET ['file']); //如果baseDir不在前面0 == strpos,很可能是黑客尝试if(strpos($ path,$ baseDir)){die('Invalid Path'); } elseif(file_exists($ path)){echo file_get_contents($ path); } else {header('HTTP/1.1 404 Not Found'); echo"无法找到请求的文件"; } (4认同)
  • realpath() 是一个好朋友,但还不够 - 如果您引用现有路径,它只返回完整路径。否则会返回 false;在某些情况下,这不会造成任何麻烦,但考虑到自动创建子目录的“另存为”操作,它可能会毁掉游戏。(用户告诉您将文件放在哪里,但您响应“无效路径”,因为 realpath 返回 false。)这可能不是您正在做的;只是想提一下。 (3认同)
  • @SeanDowney你的解​​决方案中有一个错误,即你应该检查strpos不会返回false或非零,这是你没有做的. (2认同)

phi*_*reo 12

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


Yau*_*ich 8

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 || strpos($path, $baseDir) === false) { 
   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"; 
} 
Run Code Online (Sandbox Code Playgroud)

  • 据推测,如果“strpos($path, $baseDir) === false”,则“strpos($path, $baseDir) !== 0”,因为我期望 php 中的“false !== 0”。所以似乎不需要第 5 行测试的第二部分。 (2认同)

Mat*_*iva 6

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


Che*_*oft 5

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