为了账号安全,请及时绑定邮箱和手机立即绑定

阻止PHP中的目录遍历但允许路径

/ 猿问

阻止PHP中的目录遍历但允许路径

青春有我 2019-07-20 10:10:04

阻止PHP中的目录遍历但允许路径

我有一条基本路径/任何/foo/

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

然而,我如何做到这一点(读取目录),而不允许目录遍历?

例如。

/\.\.|\.\./

不会正确过滤。


查看完整描述

3 回答

?
慕莱坞7535251

一种选择是比较真正的路径:

$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将要有任何“虚拟目录”,如......


查看完整回答
反对 回复 2019-07-20
?
浮云间

ircmaxell的回答不完全正确。我在几个片段中看到了这个解决方案,但是它有一个与realpath()..这个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!}


查看完整回答
反对 回复 2019-07-20
?
FFIVE

仅仅检查./或类似的模式是不够的。以“./”为例,哪个URI编码为“%2e%2e%2f”。如果您的模式检查发生在解码之前,您将错过这一遍历尝试。黑客还可以做一些其他的技巧来绕过模式检查器,特别是在使用编码字符串时。

正如ircmaxwell所建议的那样,我通过使用realpath()之类的方法将任何路径字符串规范化到其绝对路径,从而成功地阻止了这些事件。只有到那时,我才开始通过将遍历攻击与我预定义的基本路径相匹配来检查遍历攻击。


查看完整回答
反对 回复 2019-07-20

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信