File Upload: Webshell через загрузку в templates/
Загрузка документов сохраняет файлы в директорию templates/ без проверки содержимого. Просмотр файлов через render_template() позволяет выполнить Jinja2 SSTI.
mediumpythonPro
Задача
# File Upload: webshell через rendering загруженных файлов
## Сценарий
Перед вами Flask-приложение интернет-магазина SecureShop. У авторизованных пользователей есть возможность загружать произвольные документы — внутренний раздел «Документы» с формой загрузки и страницей просмотра загруженных файлов.
В этой реализации сошлись **две** независимые ошибки в работе с загруженными файлами, и каждая по отдельности уже опасна, а вместе они дают полноценный канал серверного исполнения произвольного кода:
1. **Хранение в служебной директории фреймворка.** Загруженные пользователем файлы кладутся в директорию **внутри** каталога шаблонов Flask — в той самой иерархии, из которой шаблонизатор Jinja2 берёт `.html`-файлы для рендеринга страниц приложения. Сама по себе эта ошибка делает любые загруженные файлы потенциально доступными как «шаблоны» (например, через перезапись по traversal — но это другая лаба).
2. **Отдача файлов через шаблонизатор.** Ещё хуже: страница просмотра загруженного документа не отдаёт файл «как файл» (через прямую отдачу содержимого), а **прогоняет его через тот же самый шаблонизатор**. То есть если в загруженном файле есть Jinja2-выражения (`{{.. }}`, `{%.. %}`), сервер их **выполняет** при отрисовке страницы.
В сочетании эти две ошибки означают: загрузил HTML-файл с Jinja2-выражением — открыл страницу просмотра документа — Jinja2 выполнил выражение в **серверном** контексте Flask-приложения. А Jinja2 в Python через цепочку «обычных» атрибутов любого объекта дотягивается до модулей работы с операционной системой и до классов запуска подпроцессов. То есть это полноценный SSTI с эскалацией до RCE — на канале «загрузка документа».
В переменных окружения процесса есть значение CTF-флага.
## Цели
1. Найдите раздел загрузки документов и эндпоинт их просмотра. Подтвердите, что просмотр загруженного файла **исполняет** Jinja2-выражения внутри него (простейший детектор — арифметическое выражение в HTML-документе, которое при просмотре вернётся вычисленным).
2. Соберите минимальный «webshell» — HTML-файл с Jinja2-выражением, которое через цепочку доступа к атрибутам Python-объектов дотянется до модуля работы с операционной системой и прочитает переменные окружения процесса.
3. Загрузите этот файл, откройте страницу просмотра — и заберите CTF-флаг прямо из ответа.
## Данные
| Параметр | Значение |
|----------|----------|
| Обычный пользователь | `demo` / `demo` |