我的剧本:
$secret = check_input($_GET['secret']);
if(isset($_POST['register'])) {
if (isset($secret) || !empty($secret)) {
if (file_exists(ROOT . '/intl/codes/' . $secret)) {
unlink(ROOT . '/intl/codes/' . $secret);
$trusted = 'yes';
} else {
$trusted = 'no';
}
}
//$_POST['register'] register details...
}
$secret
文件夹中不存在/codes/
,则会生成Warning: unlink Is a directory
如何摆脱它?$trusted
总是给yes
即使文件不存在?答案 0 :(得分:6)
要删除目录,您应该使用rmdir()
而不是unlink()
。
$secret = check_input($_GET['secret']);
if(isset($_POST['register'])) {
if (!empty($secret)) {
if(file_exists(ROOT . '/intl/codes/' . $secret)) {
rmdir(ROOT . '/intl/codes/' . $secret);
$trusted = 'yes';
} else {
$trusted = 'no';
}
}
//$_POST['register'] register details...
}
虽然这里存在严重的安全风险!如果您的check_input()
未正确清理$secret
,则可以rmdir('/intl/codes/../')
与删除/ intl /相同。
尝试这样的事情:
$allowed = ROOT. '/intl/codes/';
$path = realpath($allowed . check_input($_GET['secret']));
if(strpos($path, $allowed) === 0) { //Check that $path is within allowed directory
if(is_dir($path)) {
rmdir($path);
} else if(file_exists($path)) {
unlink($path);
} else {
echo "File/folder not found";
}
} else {
echo "Untrusted user tried to delete outside of allowed directory";
}
答案 1 :(得分:1)
答案 2 :(得分:1)
if (file_exists(ROOT . '/intl/codes/' . $secret)) {
unlink(ROOT . '/intl/codes/' . $secret);
$trusted = 'yes';
} else {
$trusted = 'no';
}
还有其他方法吗(更简单等)?
不,唯一的方法是使用file_exists
如果/ codes /文件夹中不存在$ secret,则会产生警告:unlink是一个目录如何摆脱它?
似乎$secret
指向目录。执行路径达到unlink
,因为if
部分返回true。所以它存在。要删除目录,请使用rmdir()
为什么$ trusted始终给出是,即使文件不存在?
由于unlink
会删除它并将$trusted
设置为yes
。当您在删除后进行搜索时,您会发现它不存在,但$trusted
包含yes
答案 3 :(得分:1)
显然,您的$secret
是一个空字符串,但它正在通过您的isset()
测试。
所以目录 ROOT . '/intl/codes/'
确实存在(因此通过了file_exists()
检查),但你不能unlink()
目录(这里也不是你的意图)。< / p>
确保$_GET['secret']
中有非空的内容并验证您的check_input()
功能。
P.S。您可能应该删除isset($secret)
部分条件。 <{1}}就足够了,它会修复你的脚本。
答案 4 :(得分:1)
如php文档所述file_exists()
:
Checks whether a file or directory exists
我对你的问题#3的唯一猜测是:你检查文件是否存在,确实存在。只是,它不是文件,它是目录。
对于#2,同样如错误消息所述,你可以这样做:
$ file_to_check = ROOT。 '/ intl / codes /'。 $秘密;
if (file_exists($file_to_check)) {
if( !is_dir( $file_to_check ) )
unlink($file_to_check);
else
rmdir( $file_to_check );
$trusted = 'yes';
}
对于你的#1问题,你可以做一个这样的事情:
$secret = input_get($_GET['secret']);
if(isset($_POST['register']) && !empty($secret)) {
$file_to_check = ROOT . '/intl/codes/' . $secret;
if (file_exists($file_to_check)) {
if( !is_dir( $file_to_check ) )
unlink($file_to_check);
else
rmdir( $file_to_check );
$trusted = 'yes';
} else {
$trusted = 'no';
}
}
function input_get($key, $default = ""){
if(!isset($_GET[$key])){
return $default;
} else {
//do input cleanup first, if you want
return $_GET[$key];
}
}
一点点解释:
check_input()
的作用,所以我为名为$_GET[]
的{{1}}创建了包装函数。它不需要执行input_get()
并且还填写默认值。isset()
放入变量ROOT . '/intl/codes/' . $secret;
,这样您就不必一次又一次地输入它。