Очистка пути в C++

Я пишу небольшой доступный только для чтения FTP-подобный сервер. Клиент говорит "дай мне этот файл", и мой сервер отправляет его.

Есть ли какой-нибудь стандартный способ (библиотечная функция?!?), Чтобы убедиться, что запрошенный файл не "../../../../../etc/passwd" или что-то другое? Было бы здорово, если бы я мог ограничить все запросы каталогом (и его подкаталогами).

Спасибо!

6 ответов

Решение

Получите индекс корневого каталога (/) и индекс обслуживающего каталога (скажем, /ftp/pub). Для файлов, которые они запрашивают, убедитесь, что:

  1. Файл существует.
  2. Родители файла (доступ с помощью нескольких "/.." в пути к файлу) попадают в индекс обслуживающего каталога, прежде чем он попадет в индекс корневого каталога.

Ты можешь использовать stat найти индекс любого каталога. Поместите это в одну функцию и вызовите ее перед обработкой файла.

Конечно, использование пользователя / группы с соответствующими привилегиями также будет работать.

Chroot, вероятно, лучший путь, но вы можете использовать realpath(3) определить канонический путь к заданному имени файла. Со страницы руководства:

 char *realpath(const char *file_name, char *resolved_name);

Функция realpath() разрешает все символические ссылки, дополнительные символы '/' и ссылки на /./ и /../ в имени файла и копирует полученный абсолютный путь в память, на которую ссылается разрешенное имя. Аргумент resolved_name должен ссылаться на буфер, способный хранить как минимум символы PATH_MAX.

Оттуда вы можете ограничить запрос любым дополнительным способом.

Также взгляните на chroot

Хотя это не идеально, вы можете запустить свой ftp-сервер под определенным пользователем / группой и разрешить только определенные каталоги этому пользователю / группе. Это, однако, может быть не совсем то, что вы ищете.

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

Я лично предпочитаю первое, так как эта работа уже сделана для вас ОС.

В Windows я бы сделал что-то вроде (все еще относится к любой ОС):

  1. Файл пользовательских запросов
  2. Сервер находит файл
  3. Сервер проверяет, начинается ли path_to_file с "C:/SomeFolderWithFiles/"
  4. Завершить транзакцию

Я не знаю стандартной библиотеки, которая выполняет это.

Вы можете попробовать:

  1. Установите разрешения для пользователя Unix, который работает на сервере, чтобы иметь права только на чтение / запись для определенного каталога. (возможно, используя PAM, chrooted окружение или используя стандартные разрешения пользователя / группы unix)

  2. Вы можете разработать свою программу так, чтобы она принимала только абсолютные пути (в unix - пути, начинающиеся с '/'). Таким образом, вы можете проверить, чтобы убедиться, что это правильный путь - например, запретить любой путь со строкой ".."

редактировать:

От Питера: похоже, есть библиотечная функция realpath(), которая помогает с #2 сверху.

Другие вопросы по тегам