我有一个 PHP 应用程序,它使用$_GET
参数来选择文件系统上的 JS/CSS 文件。
如果我拒绝输入字符串包含的所有请求./
, \
或者可见 7 位 ASCII 范围之外的字节,当路径传递到 PHP 的底层(基于 C)文件函数时,这是否足以防止父目录遍历?
我知道空字节漏洞 http://www.php.net/manual/en/security.filesystem.nullbytes.php,但是还有其他替代/格式错误的字符编码技巧可能会通过这些检查吗?
这是基本思想(不是生产代码):
$f = $_GET['f']; // e.g. "path/to/file.js"
// goal: select only unhidden CSS/JS files within DOC_ROOT
if (! preg_match('@^[\x20-\x7E]+$@', $f) // outside visible ASCII
|| false !== strpos($f, "./") // has ./
|| false !== strpos($f, "\\") // has \
|| 0 === strpos(basename($f), ".") // .isHiddenFile
|| ! preg_match('@\\.(css|js)$i@', $f) // not JS/CSS
|| ! is_file($_SERVER['DOCUMENT_ROOT'] . '/' . $f)) {
die();
}
$content = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/' . $f);
Update:我的问题实际上是关于 C 文件系统函数如何解释任意 ASCII 序列(例如,如果存在未记录的转义序列),但我意识到这可能取决于系统,并且在实践中可能无法回答。
我的主动验证还要求realpath($fullPath)
从...开始realpath($_SERVER['DOCUMENT_ROOT'])
,确保该文件位于 DOC_ROOT 内,但此帖子的目标是放弃realpath()
(它在各种环境中被证明是不可靠的)同时仍然允许不寻常但有效的 URI,例如/~user/[my files]/file.plugin.js
.
出于安全目的过滤输入时,请始终使用白名单,而不是后备名单。
您应该拒绝所有不匹配的路径/^([A-Za-z0-9_-]+\/?)*[A-Za-z0-9_-]+\.(js)|(css)?$/
.
这将只允许正常的分段路径,其中每个分段都有字母、数字或_-
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)