防止使用面向Web的应用程序进行目录遍历 - 正则表达式是防弹吗?

时间:2009-03-04 17:03:36

标签: php directory directory-traversal

我处于需要允许用户下载从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?

6 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:1)

我认为您可以使用htaccess

答案 3 :(得分:1)

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

  • 确保文件与文件路径看起来像
  • 的普遍接受的Regexp相匹配
  • 使用realpath(在PHP中)获取用户请求文件的规范形式并进行比较以确保它在基本目录中
  • 从PHP v5.3开始,您可以使用ini_set将open_basedir限制为特定文件夹,以便不能读取该文件夹之外的文件(使用fopen,include,fread等)

答案 4 :(得分:0)

您的文件名包含哪些字符?如果它只是[a-zA-Z0-9]单点破折号和斜线,那么随意剥去其他东西。

答案 5 :(得分:0)

我的解决方案

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

if(preg_match($pat,$reqPath)){
    echo "File found";
}else{
    echo "Access denied"
}
?>