Перейти к содержимому
← Каталог golang File Upload

File Upload: Обход расширений и Path Traversal

Сервер принимает файлы с расширением .jpg, но слепо доверяет имени файла из Content-Disposition. Используйте Path Traversal, чтобы подбросить свой токен конфигурации и получить флаг.

hardgolangPro
Задача
# File Upload: подмена имени файла как канал записи произвольного пути ## Сценарий Вы зарегистрированы в интернет-магазине **SecureShop** как пользователь **demo**. На странице профиля доступна загрузка аватара: пользователь выбирает изображение, multipart-запрос уходит на сервер, который сохраняет файл в директорию для статики. Команда уверена, что эндпоинт безопасен — пользователь не контролирует имя сохранения, контролируется лишь содержимое аватара. По данным внутреннего аудита, на сервере хранится конфиденциальная метка в переменной окружения `LAB_FLAG`, доступная коду рендеринга страниц (через зарегистрированную template-функцию); её требуется извлечь. ## Цель 1. Изучите multipart-поток, который отправляет форма загрузки аватара. Какие части запроса полностью контролируются клиентом? 2. Найдите способ направить сохранение файла за пределы директории статики — в место, где сервер использует загруженный контент при рендеринге следующих запросов. 3. Используйте этот канал, чтобы получить значение `LAB_FLAG` через template-функцию, доступную в шаблонизаторе сервера. Извлеките флаг. ## Теория Multipart-запрос включает заголовки для каждой части — в том числе `Content-Disposition` с полем `filename`, в которое браузер по умолчанию помещает оригинальное имя файла, выбранного пользователем. Это полностью **клиентский** ввод: атакующий, отправляющий запрос вручную (через curl, Burp, Python `requests`), может задать там произвольную строку — включая последовательности path traversal (`../`, абсолютные пути, кодированные эквиваленты). **Уязвимый паттерн:** ```go // Сервер использует имя файла из multipart-заголовка как часть пути сохранения filename := header.Filename // полностью контролируется клиентом uploadPath := filepath.Join("static", "img", filename) dst, _ := os.Create(uploadPath) // ../* в filename выведет за пределы static/img ``` `filepath.Join` нормализует путь, но не обрезает восходящие сегменты — поэтому `../../some/dir/file` относительно базы выводит результат за пределы статики. Самый «вкусный» класс целей для записи — файлы, которые приложение **читает и интерпретирует** при последующих запросах: HTML/Go-шаблоны (рендерятся при каждой подгрузке страницы), скрипты-бэкдоры (если есть исполняемый PHP/CGI слой), конфиги (если читаются на лету). При hot-reload шаблонов в Go перезаписанный файл подхватывается без рестарта сервера — атакующему достаточно одного запроса. ## Точка входа атаки | Параметр | Значение | |----------|----------| | Учётные данные | `demo` / `demo` | | Эндпоинт | `POST /profile/avatar` (multipart/form-data) | | Уязвимый канал | заголовок `Content-Disposition: ...; filename="..."` части `avatar` | | Доступная server-side функция шаблонизатора | `{{ env "LAB_FLAG" }}` (зарегистрирована в funcMap) | | Цель | вывести флаг через server-side рендеринг после подмены контента в одном из директорий, читаемых шаблонизатором |
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru