Райтап на задачу «Bug News»

velvetway

Автор:

velvetway

24 октября 2026

59

24.10.2026
Bug News
Категория:

Web

Задача «Bug News»

Автор:

LastTeamLead

Первая кровь:
altfoxie
Сложность:
medium
Дата публикации:
02.05.2026
Решений:
41
Рейтинг:
4.5/5
Ссылка:
Решать

Из описания таска мы узнаём, что «в проект добавлена фича с черновиками статей, которые доступны только админу, там он и прячет флаг».

Открываем страницу задания «Bug News». Нас встречает MVP-версия новостного сайта.

Главная страница задания Bug News

Стартовая страница задания на домене bug-news.t1.bug-makers.ru.

Сама страница не кликабельна, поэтому обратимся к инструментам DevTools в браузере, чтобы понять, из чего она состоит и с чем взаимодействует.

Вкладка «Сеть» в инструментах DevTools

Вкладка «Сеть» инструментов DevTools.

Кроме стандартного лендинга страницы и подгружающихся стилей, замечаем интересную API-ручку — api/articles.

Запрос к API-ручке api/articles и HTTP-заголовки

API-ручка и её заголовки.

Изучим её подробнее: для этого перейдём напрямую по соответствующему URL.

Список статей в ответе API api/articles

Содержимое api/articles.

В ответе приходит список новостей. Если присмотреться к полю id, видно, что в списке присутствуют статьи с номерами 6, 5, 4, 3 и 1, а статьи с id=2 нет. При этом по условию флаг спрятан в черновике, а из общей ленты сервер отдаёт только опубликованные статьи со статусом isPublished: true. Похоже, что пропавшая вторая статья и есть тот самый черновик. Попробуем достать её напрямую по ID — перейдём по адресу api/articles/2.

Страница ошибки при запросе api/articles/2

Переход на api/articles/2.

Но вместо статьи нас встречает страница с подробной, нестандартной ошибкой Symfony. Поищем, что это такое.

Теперь мы знаем, что это фреймворк — готовая программная основа с библиотеками и инструментами для разработки приложений на PHP.

Разберёмся подробнее, что видно на странице ошибки. Для обычной страницы с сообщением об ошибке информации здесь необычно много: есть стек, исходный код и путь к файлам приложения на сервере. Обычному пользователю такое показывать не должны, значит, включён режим отладки. Уязвимость такого типа называется раскрытием конфиденциальной информации неавторизованному субъекту (CWE-200).

Рассмотрим сам запрос.

Страница с описанием фреймворка Symfony

Информация о Symfony на сайте workspace.ru/tools/framework/symfony.

Обращаем внимание на путь приложения в стеке ошибки — /var/www/bug_pr0f1ler. Это подсказывает, что для отладки используется Symfony Profiler.

Подробная ошибка Symfony с путём к приложению

Запрос с подробной ошибкой Symfony.

Поищем, что такое profiler в контексте Symfony.

Результаты поиска о Symfony Profiler

Поиск о назначении профайлера в Symfony.

Получается, это встроенная панель отладки Symfony, режим которой включён. Узнаем, по какому адресу можно открыть профайлер.

Стартовая страница Symfony Profiler по адресу /_profiler

Стандартный адрес профайлера — /_profiler.

Перейдём на найденный адрес. Нас встречает веб-профайлер Symfony, который показывает последние запросы к приложению.

Список последних запросов в Symfony Profiler

Стартовая страница профайлера со списком последних запросов.

На странице показаны запросы. Откроем любой из них, нажав на его токен. Слева у запроса есть вкладки с деталями.

Детали запроса в панели профайлера Symfony

Карточка запроса с вкладками анализа.

Для начала нас интересует карта маршрутов приложения — вкладка Routing.

Список маршрутов приложения во вкладке Routing

Вкладка Routing: маршруты приложения.

На вкладке Routing видны все маршруты приложения. Кроме знакомого публичного /api/articles (api_articles_list), есть административные маршруты: /admin-api/articles (admin_api_articles_list), где, судя по названию, отдаются черновики; /admin-api/login-check — выдача токена; /admin/login — страница входа. Маршрута /api/articles/{id} здесь нет, поэтому ранее мы и получили 404. Попробуем напрямую открыть /admin-api/articles.

Ответ 401 при запросе к /admin-api/articles

Запрос к закрытому API без JWT-токена.

Получим ответ 401: для запроса не хватает JWT-токена. Попробуем его найти. Раз нужны секреты, а режим отладки включён, посмотрим конфигурацию приложения — вкладку Configuration.

Вкладка Configuration с настройками Symfony

Конфигурация приложения и параметры режима отладки.

Здесь видим Debug: enabled и окружение dev — это ещё раз подтверждает, что отладка открыта наружу. Нажмём View full PHP configuration.

Страница PHP configuration с информацией о PHP

Полная конфигурация PHP из Symfony Profiler.

Открывается объёмная страница с конфигурацией. Поскольку нас интересуют секреты, найдём раздел Environment.

Переменные окружения приложения в phpinfo

Раздел Environment с настройками среды приложения.

В режиме отладки здесь видны переменные окружения. Среди них важны:

  • ADMIN_API_ADMIN_LOGIN — логин администратора,

  • JWT_PASSPHRASE — пароль для приватного ключа JWT,

  • DATABASE_URL — адрес базы данных.

Сам логин указан как admin. Переменная JWT_PASSPHRASE пригодится для расшифровки ключа, которым подписываются токены.

Список бандлов, подключённых в Symfony

Среди подключённых бандлов виден Lexik JWT Bundle.

Приватный ключ нужно прочитать. Маршрут /_profiler/open позволяет профайлеру открывать файлы проекта. За JWT отвечает Lexik JWT Bundle. По умолчанию он хранит ключ в config/jwt/private.pem. В параметре file передадим путь к ключу, а line укажем равным 1.

Содержимое приватного JWT-ключа private.pem

Зашифрованный приватный ключ из проекта.

Ключ отдают в зашифрованном виде, поэтому сначала его нужно расшифровать. Для этого пригодится найденная в phpinfo переменная JWT_PASSPHRASE — пароль ключа. Используем подходящую утилиту для расшифровки, передав ей ключ и пароль.

Сервис расшифровки приватного ключа JWT

Результат расшифровки ключа с помощью JWT_PASSPHRASE.

Теперь можно подписать JWT расшифрованным ключом. В JWT.io выберем алгоритм RS256 и зададим заголовок {"alg":"RS256","typ":"JWT"}. В Payload укажем имя пользователя admin и срок действия токена, например {"username":"admin","exp":9999999999}. Поле username нужно приложению для поиска пользователя. В поле Private Key вставим расшифрованный ключ.

Настройка параметров JWT с алгоритмом RS256

Создание токена с выбранным алгоритмом и приватным ключом.

В поле Encoded JWT появится готовый токен. Теперь можно добавить его к запросу на /admin-api/articles и получить содержимое черновика.

Запрос к административному API с JWT-токеном

Итоговый запрос к черновику с токеном доступа.

В чём уязвимость?

Корень проблемы — включённый режим отладки (APP_DEBUG=1) и доступный извне Symfony Profiler. По классификации OWASP это A05:2021 — Security Misconfiguration, а утечка данных относится к CWE-200.

Из одной неверной настройки выстроилась целая цепочка: подробные ошибки раскрыли стек и пути к файлам; профайлер показал переменные окружения и позволил прочитать приватный JWT-ключ. С его помощью был подписан административный токен, что привело к обходу контроля доступа (A01:2021 — Broken Access Control).

На продакшене нужно отключить отладку (APP_DEBUG=0) и закрыть доступ к /_profiler.

Если вы нашли опечатку или ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter

Также по теме:

Райтап на задачу «OGо какая картинка»

/Разборы задач

Райтап на задачу «OGо какая картинка»

Разбираем задачу «OGо какая картинка»: изучаем Open Graph, подменяем User-Agent и ищем части флага в превью ссылок.
Прочитать

76

Разбор задачи «Тест по YAML»

/Разборы задач

Разбор задачи «Тест по YAML»

Пример того, как обновления библиотек, смена парсера или даже «безобидный» рефакторинг обработки данных могут приводить к уязвимостям. Особенно когда формат сам по себе любит неявные преобразования.
Прочитать

898