Подтвердить что ты не робот

Предотвращение обхода каталога в PHP, но допускающие пути

У меня есть базовый путь/безотносительно/foo/

и $_GET['path'] должен относиться к нему.

Как мне это сделать (чтение каталога), не разрешая обход каталога?

например.

/\.\.|\.\./

Не будет правильно фильтроваться.

4b9b3361

Ответ 1

Ну, одним из вариантов было бы сравнение реальных путей:

$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 будет не иметь какие-либо "виртуальные каталоги", такие как . или .....

Ответ 2

Ответ 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!
}

Ответ 3

Недостаточно проверять шаблоны типа../или подобных. Возьмите "../", например, URI кодирует "% 2e% 2e% 2f". Если проверка вашего шаблона происходит до декодирования, вы пропустите эту попытку обхода. Есть и другие трюки, которые хакеры могут сделать, чтобы обойти проверку шаблонов, особенно при использовании закодированных строк.

У меня был наибольший успех, останавливая их, канонизируя любую строку пути до ее абсолютного пути, используя что-то вроде realpath(), как предполагает ircmaxwell. Только после этого я начинаю проверять атаки обхода, сопоставляя их с базовым путем, который я предопределил.

Ответ 4

Вы можете попробовать использовать regex для удаления всех.. /s, но в PHP есть несколько хороших функций, которые сделают намного лучшую работу:

$page = basename(realpath($_GET));

basename - удаляет всю информацию каталога из пути, например ../pages/about.php станет about.php

realpath - возвращает полный путь к файлу, например about.php станет /home/www/pages/about.php, но только если файл существует.

В совокупности они возвращают только имя файла, но только если файл существует.

Ответ 5

Я предполагаю, что вы имеете в виду, не позволяя пользователям перемещаться по каталогу да?

Если вы пытаетесь остановить свой собственный PHP от прохождения каталога, вы должны просто сделать работу php должным образом.

Что нужно для остановки пользователей - это модифицированный файл .htaccess...

Options -Indexes

(Все это предполагает, что вы говорите о пользователях)

Ответ 6

1

положить нулевой index.htm для блока -Index

2

фильтр sQS при запуске

// Path Traversal Attack
if( strpos($_SERVER["QUERY_STRING"], "../") ){
    exit("P.T.A. B-(");
}

Ответ 7

Рассматривая создание новых файлов или папок, я подумал, что могу использовать двухэтапный подход:

Сначала проверьте попытки обхода, используя пользовательскую реализацию функции, подобной realpath(), которая, однако, работает для произвольных путей, а не только для существующих файлов. Там хорошая отправная точка здесь. Расширьте его с помощью urldecode() и всего, что, по вашему мнению, стоит проверить.

Теперь, используя этот грубый метод, вы можете отфильтровать некоторые попытки обхода, но возможно, что вы пропустили какую-то хакерскую комбинацию специальных символов, символических ссылок, экранирующих последовательностей и т.д. Но поскольку вы точно знаете, что целевой файл не существует (проверьте с помощью file_exists) никто не может ничего перезаписать. В худшем случае кто-то может получить ваш код, создавая файл или папку где-нибудь, что в большинстве случаев может быть приемлемым риском, если ваш код не позволяет им сразу записывать в этот файл/папку.

Наконец, теперь путь указывает на существующее местоположение, поэтому теперь вы можете выполнить правильную проверку, используя методы, предложенные выше, используя realpath(). Если в этот момент выясняется, что произошел обход, вы все еще в большей или меньшей степени в безопасности, при условии, что вы предотвращаете любые попытки записи в целевой путь. Также прямо сейчас вы можете удалить целевой файл /dir и сказать, что это была попытка обхода.

Я не говорю, что его нельзя взломать, так как, в конце концов, он может разрешить внесение незаконных изменений в ФС, но все же лучше, чем просто делать пользовательские проверки, которые не могут использовать realpath(), и окно для злоупотреблений оставить открытым создание временного и пустого файла или папки где-то ниже, чем предоставление им возможности сделать его постоянным и даже записать в него, как это будет происходить только с пользовательской проверкой, которая может пропустить некоторые крайние случаи.

Также поправьте меня, если я ошибаюсь, пожалуйста!