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

Web
Задача «Bug News»
Из описания таска мы узнаём, что «в проект добавлена фича с черновиками статей, которые доступны только админу, там он и прячет флаг».
Открываем страницу задания «Bug News». Нас встречает MVP-версия новостного сайта.
Сама страница не кликабельна, поэтому обратимся к инструментам DevTools в браузере, чтобы понять, из чего она состоит и с чем взаимодействует.
Кроме стандартного лендинга страницы и подгружающихся стилей, замечаем интересную API-ручку — api/articles.
Изучим её подробнее: для этого перейдём напрямую по соответствующему URL.
В ответе приходит список новостей. Если присмотреться к полю id, видно, что в списке присутствуют статьи с номерами 6, 5, 4, 3 и 1, а статьи с id=2 нет. При этом по условию флаг спрятан в черновике, а из общей ленты сервер отдаёт только опубликованные статьи со статусом isPublished: true. Похоже, что пропавшая вторая статья и есть тот самый черновик. Попробуем достать её напрямую по ID — перейдём по адресу api/articles/2.
Но вместо статьи нас встречает страница с подробной, нестандартной ошибкой Symfony. Поищем, что это такое.
Теперь мы знаем, что это фреймворк — готовая программная основа с библиотеками и инструментами для разработки приложений на PHP.
Разберёмся подробнее, что видно на странице ошибки. Для обычной страницы с сообщением об ошибке информации здесь необычно много: есть стек, исходный код и путь к файлам приложения на сервере. Обычному пользователю такое показывать не должны, значит, включён режим отладки. Уязвимость такого типа называется раскрытием конфиденциальной информации неавторизованному субъекту (CWE-200).
Рассмотрим сам запрос.
Обращаем внимание на путь приложения в стеке ошибки — /var/www/bug_pr0f1ler. Это подсказывает, что для отладки используется Symfony Profiler.
Поищем, что такое profiler в контексте Symfony.
Получается, это встроенная панель отладки Symfony, режим которой включён. Узнаем, по какому адресу можно открыть профайлер.
Перейдём на найденный адрес. Нас встречает веб-профайлер Symfony, который показывает последние запросы к приложению.
На странице показаны запросы. Откроем любой из них, нажав на его токен. Слева у запроса есть вкладки с деталями.
Для начала нас интересует карта маршрутов приложения — вкладка 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: для запроса не хватает JWT-токена. Попробуем его найти. Раз нужны секреты, а режим отладки включён, посмотрим конфигурацию приложения — вкладку Configuration.
Здесь видим Debug: enabled и окружение dev — это ещё раз подтверждает, что отладка открыта наружу. Нажмём View full PHP configuration.
Открывается объёмная страница с конфигурацией. Поскольку нас интересуют секреты, найдём раздел Environment.
В режиме отладки здесь видны переменные окружения. Среди них важны:
ADMIN_API_ADMIN_LOGIN — логин администратора,
JWT_PASSPHRASE — пароль для приватного ключа JWT,
DATABASE_URL — адрес базы данных.
Сам логин указан как admin. Переменная JWT_PASSPHRASE пригодится для расшифровки ключа, которым подписываются токены.
Приватный ключ нужно прочитать. Маршрут /_profiler/open позволяет профайлеру открывать файлы проекта. За JWT отвечает Lexik JWT Bundle. По умолчанию он хранит ключ в config/jwt/private.pem. В параметре file передадим путь к ключу, а line укажем равным 1.
Ключ отдают в зашифрованном виде, поэтому сначала его нужно расшифровать. Для этого пригодится найденная в phpinfo переменная JWT_PASSPHRASE — пароль ключа. Используем подходящую утилиту для расшифровки, передав ей ключ и пароль.
Теперь можно подписать JWT расшифрованным ключом. В JWT.io выберем алгоритм RS256 и зададим заголовок {"alg":"RS256","typ":"JWT"}. В Payload укажем имя пользователя admin и срок действия токена, например {"username":"admin","exp":9999999999}. Поле username нужно приложению для поиска пользователя. В поле Private Key вставим расшифрованный ключ.
В поле Encoded JWT появится готовый токен. Теперь можно добавить его к запросу на /admin-api/articles и получить содержимое черновика.
Корень проблемы — включённый режим отладки (APP_DEBUG=1) и доступный извне Symfony Profiler. По классификации OWASP это A05:2021 — Security Misconfiguration, а утечка данных относится к CWE-200.
Из одной неверной настройки выстроилась целая цепочка: подробные ошибки раскрыли стек и пути к файлам; профайлер показал переменные окружения и позволил прочитать приватный JWT-ключ. С его помощью был подписан административный токен, что привело к обходу контроля доступа (A01:2021 — Broken Access Control).
На продакшене нужно отключить отладку (APP_DEBUG=0) и закрыть доступ к /_profiler.