我处于需要允许用户下载从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?
答案 0 :(得分:8)
我建议使用realpath()
将路径转换为绝对路径。然后,您可以将结果与允许目录的路径进行比较。
答案 1 :(得分:3)
我不是PHP开发人员,但我可以告诉你,对这种情况使用基于正则表达式的保护就像穿T恤一样抵御飓风。
这种问题在安全用语中被称为规范化漏洞(在应用程序有机会将其转换为绝对文件路径之前,您的应用程序会解析给定的文件名)。攻击者将能够提出任意数量的文件名排列,这几乎肯定无法与你的正则表达式相匹配。
如果您必须使用Regex,请尽可能使其悲观(仅匹配 有效文件名,拒绝其他内容)。我建议您对PHP中的规范化方法进行一些研究。
答案 2 :(得分:1)
我认为您可以使用htaccess。
答案 3 :(得分:1)
我认为以下3项检查可能是理想的解决方案
答案 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"
}
?>