Вы должны только подтвердить ввод, прежде чем использовать его.
Например, вы можете разрешить только символы a-z
и /
, чтобы разрешить подкаталоги. Возможно, вы также захотите разрешить .
. Если вы сделаете это подмножество маленьким, легко проверить, разрешены ли введенные или нет допустимые символы.
На данный момент вы позволяете .
, как вы заметили, у вас есть проблема, что относительные пути могут быть созданы как /../../
, которые могут быть использованы для обходных атак.
Чтобы проверить, содержит ли строка только символы определенного диапазона, вы можете проверить это с помощью регулярного выражения или функций фильтра. Если ваш сайт не должен допускать никаких относительные части пути вы можете посмотреть, если они существуют на пути, чтобы подтвердить ввод:
$valid = !array_intersect(array('', '.', '..'), explode('/', $path));
Действительно будет FALSE
, если есть какая-либо //
или /./
или /../
часть внутри пути ,
Если вам необходимо разрешить относительные пути, то уже предложено realpath
, поэтому сначала запрашивайте входные данные против вашей структуры каталогов. Я бы использовал его только в качестве крайней меры, поскольку он относительно дорог, но об этом хорошо знать.
Однако вы можете решить эту строку ваш собственный, а с некоторой простой функции, как следующий:
/**
* resolve path to itself
*
* @param string $path
* @return string resolved path
*/
function resolvePath($path)
{
$path = trim($path, '/');
$segmentsIn = explode('/', $path);
$segmentsOut = array();
foreach ($segmentsIn as $in)
{
switch ($in)
{
case '':
$segmentsOut = array();
break;
case '.':
break;
case '..';
array_pop($segmentsOut);
break;
default:
$segmentsOut[] = $in;
}
}
return implode('/', $segmentsOut);
}
Использование:
$tests = array(
'hello',
'world/.',
'../minka',
'../../42',
'../.bar',
'../hello/path/./to/../../world',
);
foreach($tests as $path)
{
printf("%s -> %s\n", $path, resolvePath($path));
}
Выход:
hello -> hello
world/. -> world
../minka -> minka
../../42 -> 42
../.bar -> .bar
../hello/path/./to/../../world -> hello/world
я могу только предложите сначала проверить вход на основе его собственных данных, прежде чем позволять касаться его файловой системы, накануне n до realpath
.
В значительной степени моя идея, но немного лучше и быстрее;) +1 –
звучит как очень хорошее решение! Я постараюсь, чтобы он принял решение и принял ваш ответ! – speendo