我在后台运行php管理面板和纯ftpd服务器。
我想检查用户为特定用户提供的路径是否不包含..//..或/。。/
我正在使用一个php框架Nette,对于此验证,我正在使用addRule(Form::P ATTERN,'error message',$pattern((Nette api-docs:https://api.nette.org/2.4/Nette.Forms.Form.html,Nette docs:https://doc.nette.org/en/2.4/form-validation
谢谢你的时间
你是否对其他解决方案持开放态度,但如果是我,我不会尝试在路径上使用正则表达式,因为 PHP 有更简单的方法。
如果是我,我会这样做:
<?php
// You know your users are limited to their own home directory
$user_base_dir = '/home/skunkbad/';
// And they supply some path that attempts directory transversal
$supplied_path = '/home/skunkbad/../../etc/';
// Realpath in this case would return "/etc/"
$realpath = realpath( $supplied_path );
// So the check to see if the user base directory is in the path that realpath returns would fail
if( stripos( $realpath, $user_base_dir ) !== 0 )
echo 'Invalid Path!';
请参阅:http://php.net/manual/en/function.realpath.php
以及:http://php.net/manual/en/function.stripos.php
谢谢你@BrianGottier,
但是realpath($path)
检查文件是否真的存在于文件系统中,脚本需要权限才能执行......所以,自从我知道我在寻找什么以来,我用谷歌搜索了一下,并从 php.net 和社区的一些东西中提出了这个:
/**
* @param $path
* @param $baseDir
* @return bool
*/
protected function isDirValid($path, $baseDir)
{
if (stripos($path, '\'))
return false;
$path = str_replace('/', '/', $path);
$path = str_replace('\', '/', $path);
$parts = array_filter(explode('/', $path), 'strlen');
$absolutes = [];
foreach ($parts as $part)
{
if ('.' == $part)
continue;
if ('..' == $part)
{
array_pop($absolutes);
} else {
$absolutes[] = $part;
}
}
$realDir = '/' . implode('/', $absolutes);
if (stripos($realDir, $baseDir) !== 0)
return false;
return true;
}