4

我处于需要允许用户下载从 URL 动态确定的文件的情况。在下载开始之前,我需要做一些身份验证,所以下载必须先通过脚本运行。所有文件都将存储在 Web 根目录之外,以防止手动下载。

例如,以下任何内容都可能是下载链接:

基本上,文件夹深度可以变化。

为了防止目录遍历,比如说: http://example.com/downloads/../../../../etc/passwd 我显然需要对 URI 进行一些检查。(注意:我没有将此信息存储在数据库中的选项,必须使用 URI)

以下正则表达式是否可以确保用户没有输入可疑内容:

preg_match('/^\/([-_\w]+\/)*[-_\w]+\.(zip|gif|jpg|png|pdf|ppt|png)$/iD', $path)

我还有哪些其他选项可以确保 URI 正常?可能在 PHP 中使用 realpath?

4

6 回答 6

7

我建议使用realpath()将路径转换为绝对路径。然后,您可以将结果与允许目录的路径进行比较。

于 2009-03-04T17:09:37.487 回答
3

我不是 PHP 开发人员,但我可以告诉您,在这种情况下使用基于正则表达式的保护就像穿着 T 恤抵御飓风。

这种问题在安全术语中被称为规范化漏洞(您的应用程序在操作系统有机会将其转换为绝对文件路径之前解析给定文件名)。攻击者将能够想出任意数量的文件名排列,这些排列几乎肯定无法与您的正则表达式匹配。

如果您必须使用正则表达式,则使其尽可能悲观(匹配有效文件名,拒绝其他任何内容)。我建议您对 PHP 中的规范化方法进​​行一些研究。

于 2009-03-04T17:17:34.673 回答
1

我认为您可以为此使用htaccess 。

于 2009-03-04T17:08:42.403 回答
1

我认为以下 3 项检查可能是一个理想的解决方案

  • 确保文件与文件路径看起来像的普遍接受的正则表达式匹配
  • 使用 realpath(在 PHP 中)获取用户请求文件的规范形式并进行比较以确保它位于基本目录中
  • 从 PHP v5.3 开始,您可以使用 ini_set 将 open_basedir 限制为特定文件夹,这样就不可能读取该文件夹之外的文件(使用 fopen、include、fread 等)
于 2009-03-04T20:32:29.167 回答
0

您的文件名将包含哪些字符?如果它只是 [a-zA-Z0-9] 单点破折号和斜线,则可以随意剥离其他任何内容。

于 2009-03-04T17:07:48.737 回答
0

我的解决方案

$filesPath = realpath(".");
$reqPath = realpath($_GET["file"]);
$pat = "%^".preg_quote($filesPath)."%";

if(preg_match($pat,$reqPath)){
    echo "File found";
}else{
    echo "Access denied"
}
?>
于 2011-02-16T12:39:01.753 回答