2011-11-16 55 views
4

请求清理$_GET['']的最佳方法是什么?我想只允许从一个目录下载文件。

$baseDir = "/home/html/xy.com/public_html/downloads/";  
$path = realpath($baseDir . $_GET['file']); 

下一步是什么?

+1

那你应该绝对不允许'..' –

+0

这是全部吗?之后,我的脚本将是安全的? – Adrian

+0

不,不允许使用'/'和其他文件中不存在的字符。 – jli

回答

13

这里是我会在行之后你有没有:

if (dirname($path) === $baseDir) { 
    //Safe 
} 

http://php.net/dirname

基本上,做发送任何该文件实际上是在你支持一个路径前的检查。请注意,您还必须在文件名前($path)添加自己的/,并将其从$baseDir定义中删除,因为dirname()不会留下尾随路径分隔符。

+0

我必须在路径中禁用“/”,“..”和其他字符,否则在此之后不需要?谢谢。 – Adrian

+3

@阿德里安,你应该真的明白这是如何工作的,然后再继续。如果你不这样做,你的脚本有可能会变得危险。我的方法确保'$ path'中文件的路径与'$ baseDir'中指定的路径相同。如果有人使用'..'或'/',那么这些路径将不再匹配。因此,这是安全的。你理解这一点很重要。如果您正在检查多个目录,则问题会变得更加复杂。 – Brad

+0

+1对于Brad的评论。理解你需要对文件系统访问极其偏执是至关重要的。 – toon81

3

而不是后检查没有相对路径碎片存在,更容易马上剥离它们。只需使用basename()立即当你获取值:

$baseDir = "/home/html/xy.com/public_html/downloads/";  
$path = realpath($baseDir . basename($_GET['file'])); 

已经保证它不能从基本目录中向上或向下移动。

+0

谢谢,我把这个与Brad的解决方案结合起来。 :) – Adrian

+0

如果'../'在$ _GET中输入,该怎么办? –

+0

@tazotodua如果你阅读关于使用'basename()'的答案呢? – mario