Предотвращение обхода каталога с помощью веб-приложения - являются ли регулярные выражения пуленепробиваемыми? - PullRequest
4 голосов
/ 04 марта 2009

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

Например, ссылки на скачивание могут быть следующими:

Как правило, глубина папки может варьироваться.

Чтобы предотвратить обход каталога, например, скажите: http://example.com/downloads/../../../../etc/passwd Мне нужно сделать некоторую проверку URI. (Примечание: у меня нет возможности хранить эту информацию в базе данных, должен использоваться URI)

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

preg_match('/^\/([-_\w]+\/)*[-_\w]+\.(zip|gif|jpg|png|pdf|ppt|png)$/iD', $path)

Какие еще варианты, чтобы убедиться, что URI нормальный, у меня есть? Возможно использование realpath в PHP?

Ответы [ 6 ]

8 голосов
/ 04 марта 2009

Я бы рекомендовал использовать realpath() для преобразования пути в абсолют. Затем вы можете сравнить результат с путем (ами) к разрешенным каталогам.

3 голосов
/ 04 марта 2009

Я не PHP-разработчик, но могу вам сказать, что использование защиты на основе Regex для такого сценария похоже на ношение футболки от урагана.

Эта проблема известна как каноническая уязвимость на языке безопасности (когда ваше приложение анализирует заданное имя файла до того, как ОС сможет преобразовать его в абсолютный путь к файлу). Злоумышленники смогут найти любое количество изменений имени файла, которое почти наверняка не будет соответствовать вашему регулярному выражению.

Если вы должны использовать Regex, сделайте его настолько пессимистичным, насколько это возможно (соответствует только действительным именам файлов, отклоните все остальное). Я бы посоветовал вам немного изучить методы канонизации в PHP.

1 голос
/ 04 марта 2009

Я думаю, что следующие 3 проверки могут быть идеальным решением

  • Убедитесь, что файл соответствует общепринятому регулярному выражению того, как может выглядеть путь к файлу
  • Используйте realpath (в PHP), чтобы получить каноническую форму запрашиваемого пользователем файла и сравнить его, чтобы убедиться, что он находится в базовом каталоге
  • Начиная с PHP v5.3, вы можете использовать ini_set, чтобы ограничить open_basedir определенной папкой, чтобы файлы вне этой папки не могли быть прочитаны (с fopen, include, fread и т. Д.)
1 голос
/ 04 марта 2009

Я думаю, вы могли бы использовать htaccess для этого.

0 голосов
/ 16 февраля 2011

Мое решение

$filesPath = realpath(".");
$reqPath = realpath($_GET["file"]);
$pat = "%^".preg_quote($filesPath)."%";

if(preg_match($pat,$reqPath)){
    echo "File found";
}else{
    echo "Access denied"
}
?>
0 голосов
/ 04 марта 2009

Какие символы будут содержать ваши имена файлов? Если это просто [a-zA-Z0-9] одноточечные штрихи и косые черты, не стесняйтесь лишать что-либо еще.

...