2010-11-17 101 views
26

我有一个基本路径/不管/富/防止目录遍历在PHP,但允许路径

$_GET['path']应该是相对于它。

但是,我怎么做到这一点(读取目录),而不允许目录遍历?

例如。

/\.\.|\.\./ 

无法正确过滤。

回答

0

我假定你的意思,而不允许用户遍历目录是吗?

如果你想阻止你自己的PHP遍历目录,你应该首先让php正常工作。

你需要什么来阻止用户是修改.htaccess文件...

Options -Indexes 

(这一切都假定你正在谈论的用户)

+0

MainMa了解我想要实现的目标。 – Johnny 2010-11-17 14:16:34

+0

他提出了'$ _GET',显然他试图阻止黑客攻击目录,所以请不要说“你应该让php正常工作”。 – FluorescentGreen5 2017-06-29 01:55:26

93

那么,一个选择是比较真实的路径:

$basepath = '/foo/bar/baz/'; 
$realBase = realpath($basepath); 

$userpath = $basepath . $_GET['path']; 
$realUserPath = realpath($userpath); 

if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) { 
    //Directory Traversal! 
} else { 
    //Good path! 
} 

基本上,realpath()将解决提供路径的实际硬的物理路径(解析的符号链接,.../,//等)...所以,如果真正的用户路径不是以真正的基础路径开始的,那么它试图进行遍历。注意,realpath输出将有任何“虚拟目录”,如... ...

+2

这是唯一正确的方法.. – 2012-10-08 07:32:57

+0

编辑:strpos已经是多字节安全的。引入MB选择可能会引入其他漏洞... – ircmaxell 2014-02-10 18:42:08

+1

符号链接怎么样?或者如果我们想要检查的文件不存在呢? (即以预期的路径创建新文件)。 – Petah 2014-02-27 00:03:08

4

这是不够的检查像../图案或喜欢。以“../”为例,哪个URI编码为“%2e%2e%2f”。如果您的模式检查发生在解码之前,您将错过此遍历尝试。黑客可以采取一些其他技巧来规避模式检查程序,特别是在使用编码字符串时。

我有过的最成功的任何进行规范化路径字符串使用类似的realpath()作为ircmaxwell表明其绝对路径阻止这些。只有这样我才能开始通过将它们与预定义的基本路径进行匹配来检查遍历攻击。

12

ircmaxell的回答并不完全正确。我已经在几个代码片段中看到了这个解决方案,但它有一个与realpath()的输出有关的bug。该realpath()功能去掉尾随目录分隔符,所以可以想象两个相邻的目录,例如:

/foo/bar/baz/ 

/foo/bar/baz_baz/ 

由于realpath()会删除最后一个目录分隔符,你的方法将返回“善道”如果$_GET['path']等于” ../ baz_baz”,因为它会是这样的

strpos("/foo/bar/baz_baz", "/foo/bar/baz") 

可能:

$basepath = '/foo/bar/baz/'; 
$realBase = realpath($basepath); 

$userpath = $basepath . $_GET['path']; 
$realUserPath = realpath($userpath); 

if ($realUserPath === false || strcmp($realUserPath, $realBase) !== 0 || strpos($realUserPath, $realBase . DIRECTORY_SEPARATOR) !== 0) { 
    //Directory Traversal! 
} else { 
    //Good path! 
} 
+1

“strcmp”在你的代码中做了什么? – Andrew 2016-06-17 19:47:00

1

你可能会去尝试,并使用正则表达式来删除所有../s但也有PHP内置了一些不错的功能会做一个更好的工作:

$页=基名(真实路径($ _ GET));

基名 - 剔除从路径如../pages/about.php将成为所有目录信息.PH p

realpath - 返回文件的完整路径例如about.php会成为/home/www/pages/about.php,但只有在文件存在的情况下。

它们结合在一起只返回文件名,但只有当文件存在时才返回。

+0

我不认为这可以防止遍历! – Gerfried 2018-03-09 18:46:32