Path Traversal через обход нормализации пути
Нормализация пути применяется ДО конкатенации с базовым каталогом — traversal-последовательности сохраняются после Clean, позволяя читать произвольные файлы.
hardphpPro
Задача
# Path Traversal через обход однопроходной фильтрации
## Сценарий
Интернет-магазин SecureShop предлагает страницу скачивания файлов — превью-изображения товаров доступны по эндпоинту `/download?file=`. Разработчик знал об угрозе path traversal и добавил «защиту» — простую однопроходную замену последовательностей `../` и `..\` на пустую строку через `str_replace`. По его задумке, любой пользовательский ввод, содержащий traversal-конструкции, после фильтра должен превратиться в безопасное имя файла.
Однако реализация уязвима: `str_replace` выполняет ровно один проход замены и не учитывает, что после удаления запрещённой подстроки оставшиеся символы могут снова сформировать ту же подстроку. Это классическая ошибка blacklist-фильтрации — пытаться удалить «опасные» паттерны вместо проверки результата.
## Класс уязвимости
CWE-22 — Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'). Подкласс: обход фильтрации через вложенные конструкции. Реалистичный сценарий: разработчик считает свою однопроходную замену достаточной защитой, не предусматривая, что вложенные структуры обойдут фильтр.
## Цели
1. Изучить эндпоинт `/download` и определить, какая фильтрация применяется к пользовательскому вводу
2. Подобрать payload-конструкцию, обходящую однопроходную замену `../` через вложение
3. Подобрать число повторов выбранной конструкции по реакции сервера на разную глубину
4. Прочитать файл с флагом и извлечь из ответа значение `flag{...}`
## Возможные техники обхода
- **Вложенный traversal**: `....//` — после однопроходного удаления `../` из середины снова собирается `../` из крайних символов
- **Альтернативные вложения**: `..././`, `....\/`, и другие конструкции с двумя `..` вокруг разделителя
- **URL-кодирование**: `%2e%2e%2f` — закодированный `../`, который может обойти фильтр, если декодирование происходит после фильтра
- **Двойное URL-кодирование**: `%252e%252e%252f` — после первого декодирования веб-сервером становится `%2e%2e%2f`, который не совпадает со строкой `../` в фильтре
## Данные
| Параметр | Значение |
|----------|----------|
| Эндпоинт загрузки | `/download?file=` |
| Страница каталога файлов | `/downloads` |
| Базовый каталог легитимных файлов | `static/img/` |
| Где лежит флаг | стандартная системная директория временных файлов |
| Способ выхода | подбор payload + достаточная глубина повторов |
| Доступ к эндпоинту | без аутентификации |
## Источник флага
Флаг — значение переменной окружения `LAB_FLAG`, записанное при старте контейнера в файл, лежащий в стандартной системной директории для временных файлов. Формат: `flag{...}`. Эндпоинт `/download` после обхода фильтра отдаст содержимое этого файла как обычный octet-stream — открыв файл, увидите строку флага целиком.
## Реалистичность
Однопроходные `str_replace`-фильтры на traversal — массовый антипаттерн в legacy PHP-приложениях. Разработчик читает в интернете «нужно блокировать `../`», добавляет одну строку замены и считает задачу закрытой. Подобные обходы регулярно встречаются в CVE legacy CMS (Joomla, WordPress-плагины, кастомные галереи изображений). Эта лаба воспроизводит реалистичный паттерн «защита через очистку входа» и демонстрирует его принципиальную ненадёжность.