Всем привет! С вами Михаил Ключников, в мире багхантинга также известный как n1. Я работаю в Positive Technologies уже 10 лет, где руковожу группой по анализу защищенности ПО. Мы занимаемся поиском новых уязвимостей (0-day) и воспроизведением уже известных (1-day) для нужд пентестов. Еще я состою в команде PT SWARM: ее участники пишут статьи, делают различные типсы и разборы уязвимостей по горячим следам.

У меня довольно большой опыт в багхантинге на различных международных платформах и на российской Standoff Bug Bounty. В этой статье я хочу поделиться своим опытом работы с 1-day уязвимостями — багами, которые могут быть опасны, хотя для них уже вышел патч. Мы разберем жизненный цикл уязвимости, способы их мониторинга, инструменты анализа, методы воспроизведения и правила репортинга. Вы узнаете, как правильно работать с 1-day в рамках багбаунти, чтобы не тратить время впустую и добиваться результата.

Статья носит исключительно информационный характер и не является инструкцией или призывом к совершению противоправных действий. Ее цель — исключительно образовательная: рассказать о существующих уязвимостях, которыми могут воспользоваться злоумышленники, предостеречь пользователей и дать рекомендации по защите. Автор не несет ответственности за неправомерное использование опубликованной информации.

Жизненный цикл уязвимости: 0-day и 1-day

Начнем с основ. Любая уязвимость проходит несколько стадий:

  • Появление в коде. Чаще всего это происходит непреднамеренно, из-за ошибки разработчика.

  • Обнаружение. Исследователь (белый хакер) находит баг и ответственно сообщает об этом вендору.

  • Разработка патча. Вендор готовит исправление, сроки создания которого зависят от политики компании. Например, у Cisco патчи выходят по расписанию, а у некоторых вендоров — довольно оперативно.

  • Публикация. Выходит адвайзори, назначается CVE или БДУ, вендор благодарит исследователя и выплачивает вознаграждение

Где тогда проходит граница между 0-day и 1-day? Zero day (0-day, уязвимость нулевого дня) — это уязвимость с момента обнаружения до выхода патча. О ней в идеале знают только исследователь и вендор. Как только патч становится публичным, баг переходит в категорию 1-day. Формально 1-day — это любая исправленная уязвимость, даже трехлетняя, но в среде исследователей обычно принято называть 1-day относительно свежие баги (до одного-двух месяцев).

Мониторинг уязвимостей

Чтобы не пропустить свежую 1-day уязвимость, нужно держать руку на пульсе. Я рекомендую три основных источника информации об уязвимостях: базы данных и агрегаторы, адвайзори вендоров, а также соцсети.

GitHub-репозиторий CVEProject/cvelistV5

Если вы хотите видеть новые CVE максимально оперативно, мониторьте именно этот репозиторий. Обновления там появляются почти в реальном времени — например, за 26 минут до моего выступления было добавлено 34 новых уязвимости. На сайте cve.org они появляются с некоторой задержкой.

Агрегатор dbugs

Это бесплатный сервис, который собирает информацию из множества источников (X, Reddit, Telegram). Dbugs показывает тренды, позволяет фильтровать уязвимости по продуктам, вендорам, скору (оценке CVSS), а также дает ссылки на разборы уязвимостей. Правда, к скору я бы относился осторожно, так как разные компании его считают по-своему. Обратите внимание также на пометку «есть эксплойт» — это сигнал, что уязвимость уже активно используется.

Адвайзори

Иногда адвайзори (рекомендации по безопасности) вендоров выходят раньше, чем CVE попадает в базу. Например, для уязвимости CVE-2023-22518 адвайзори появился 30 октября, а в базе CVE — только 31 октября. Поэтому важно отслеживать страницы конкретных продуктов и вендоров, которые вас интересуют.

Дополнительные источники

Советую также отслеживать различные коммиты и диффы в проектах open-source, changelog (журналы изменений). Бывает, что исправление уже появилось, а CVE не назначили. Это значит, что публично об этой уязвимости мало кто знает. В этом случае мы можем использовать ИИ, чтобы выяснить, является ли исправление фиксом какой-то уязвимости. Такой мониторинг может дать фору в несколько дней.

Кроме того, политики раскрытия у вендоров различаются. Например, GitLab через 30 дней после фикса публикует полный отчет исследователя. Это отличный источник, который также можно использовать.

Соцсети

Это, конечно, must have. Я всегда был поклонником комьюнити в бывшем твиттере, но российский сегмент (различные каналы в Telegram) тоже сейчас неплохо подтянулся. Именно в соцсетях исследователи оперативно делятся первыми подробностями об уязвимости, PoC-кодом или просто предостерегают. В PT SWARM мы тоже публикуем посты о воспроизведении различных уязвимостей, чтобы предупредить сообщество.

Что и как искать в рамках багбаунти

Поток уязвимостей огромен, и чтобы в нем не утонуть, нужно понимать, что мы ищем.

Коробочные продукты на периметре

Нас интересуют готовые решения (Confluence, Exchange, ERP-системы), которые могут быть доступны извне. Если вы работаете в багбаунти, то у вас есть список активов программы — мониторьте именно их, используя собственные системы для сканирования. Shodan и Censys можно использовать как дополнение, но не стоит полагаться только на них. Для российских программ багбаунти данные этих сервисов могут быть неполными из-за ограничений по геолокации IP.

Здесь я рекомендую подключать LLM для идентификации продуктов по главной странице — нейросети отлично справляются с задачей распознавания ПО.

Фреймворки, библиотеки, вспомогательный софт

Не ограничивайтесь видимыми продуктами. Если вы исследуете, например, облачного провайдера, он может использовать OpenStack, ClickHouse или другие технологии на бэкенде. Обнаружив баг в таком компоненте, вы сможете его применить к конкретному вендору.

Критерии отбора уязвимостей

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

Воспроизведение уязвимости

Полный процесс воспроизведения CVE-2022-22518 в Atlassian Confluence, которую мы использовали для демонстрации, занял несколько часов, но я выделил его ключевые этапы.

Важно! Никогда не применяйте подобные эксплойты на продакшн-системах. Если вы обнаружили уязвимость, нужно сообщить об этом вендору. В рамках пентеста или багбаунти всегда согласовывайте свои действия с владельцами системы.

Подготовка стенда

Нам нужны две версии софта — уязвимая (8.3.3) и исправленная (8.3.4). Это необходимо для того, чтобы затем мы их сравнили и смогли локализовать проблему. Начинаем с того, что поднимаем стенд локально, чтобы было проще тестить и проверять наши гипотезы, настраиваем инфраструктуру, выкачиваем исходный код и приступаем к анализу. В некоторых случаях можем настроить удаленную отладку.

Для быстрого развертывания Confluence я использовал Docker Hub. Это очень удобно. Также для поиска софта можно использовать официальные образы, включая триальные версии, если они доступны у вендора.

Извлечение исходного кода

После этого мы выгружаем исходные коды анализируемых версий (Confluence 8.3.3 и 8.3.4). Проблема при сравнении Java-архивов (JAR) в Confluence в том, что из-за суффиксов с цифрами версий в именах файлов стандартный дифф ошибочно интерпретирует библиотеки как удаленные или добавленные элементы, захламляя результат. Чтобы устранить это искажение, используем простой кастомный скрипт, автоматически «зачищающий» суффиксы в именах JAR-файлов. Это позволяет корректно сопоставлять файлы между версиями еще до начала глубинного анализа.

Фильтрация

Далее необходимо оставить только те JAR-файлы, которые относятся непосредственно к коду Confluence, исключая стандартные сторонние библиотеки. Существует специализированный инструмент, который решает эту задачу через сборку локальной базы Maven и .NET, однако его развертывание требует загрузки нескольких гигабайт данных. Вместо этого я использовал свой кастомный скрипт jar_analyzer. Он работает в реальном времени, напрямую обращаясь к репозиторию Maven для проверки хэшей файлов без локальной базы.

Запустив этот скрипт на 960 JAR-файлах, мы отсекли всю стороннюю «библиотечную» часть, сократив массив до 427 значимых элементов в папке clear_jars. Это вдвое уменьшает объем данных для последующего сравнения (дифф), позволяя сосредоточиться на целевых изменениях в коде Confluence.

Декомпиляция

Для декомпиляции Java-кода мы использовали CFR. В качестве альтернативы можно использовать FernFlower. Различные декомпиляторы могут по-разному обрабатывать код: если один зависнет на каком-то файле, то другой успешно его разберет. Поэтому важно иметь под рукой альтернативу. При этом эти инструменты декомпилируют исключительно классы (.class-файлы), но не достают из JAR-файлов ресурсы. А нам в случае с Confluence, например, важно извлечь ресурсы. Для этого я использовал JADX в консольном режиме.

Сравнение версий

После декомпиляции папки с исходным кодом и ресурсами для обеих версий готовы к сравнению.

Для этой задачи есть два удобных опенсорс-инструмента. Meld прост в освоении и использовании, но он менее гибкий. Его неоспоримый плюс — кроссплатформенность. С другой стороны, есть более сложный WinMerge, который работает только под Windows, но он значительно быстрее, а также позволяет гибко настраивать фильтры для отсева однотипных изменений.

В нашем случае мы использовали WinMerge. Когда отключили все фильтры, изменений оказалось очень много. Затем мы применили фильтры, чтобы убрать массовые добавления одних и тех же аннотаций, например @WebSudoRequired и @AdminOnly. Сравнив версии, мы увидели, что была произведена работа с WebSudoInterceptor, и были добавлены какие-то директивы.

Локализация уязвимости

Мы заметили, что изменения затронули механизм WebSudo — функционал Confluence, который требует повторного ввода пароля при доступе к админским функциям. Разобравшись в архитектуре (фреймворк Struts), мы изучили код интерцептора WebSudoInterceptor. Оказалось, что проверка match пропускает запросы, если URI начинается с /json/ — расширенного namespace, который наследует все админские URL. При этом сам класс-обработчик (например, SetupRestoreAction) должен иметь аннотацию @WebSudoRequired, чтобы активировать проверку. В уязвимой версии 8.3.3 эта аннотация отсутствовала. В результате запрос к /json/setup-restore.action проходит без какой‑либо аутентификации и данный URL доступен любому неавторизованному пользователю.

Тестирование

Для воспроизведения уязвимости мы подготовили простой скрипт на Python, который:

  • принимает URL целевого экземпляра Confluence и путь к ZIP-архиву;

  • добавляет специальный заголовок X-Atlassian-Token: no-check, чтобы обойти защиту от CSRF (это особенность продуктов Atlassian);

  • отправляет POST-запрос на /json/setup-restore.action с ZIP-архивом определенной структуры.

ZIP-архив был сформирован так, чтобы при восстановлении сайта в систему добавлялись новые пользователи с правами администратора. В нашем случае скрипт создал учетные записи admin и ptswarm с паролем 123456.

После выполнения скрипта мы успешно залогинились под созданным администратором и убедились, что конфигурация Confluence полностью перезаписана. Нам доступен полный административный доступ к системе, что в дальнейшем позволит перейти к выполнению произвольного кода (RCE) и проникновению во внутреннюю сеть организации. Этот PoC наглядно демонстрирует, как критичная уязвимость может быть использована без аутентификации.

Важно! Никогда не применяйте подобные эксплойты на продакшн-системах. Если вы обнаружили уязвимость, нужно сообщить об этом вендору. В рамках пентеста или багбаунти всегда согласовывайте свои действия с владельцами системы.

Репортинг

Когда PoC готов, наступает этап подготовки отчета. Здесь главное — внимательно изучить правила программы багбаунти. У каждого вендора своя политика приема 1-day и 0-day:

  • Одни устанавливают конкретные временные рамки (например, 10 дней).

  • Другие вообще не принимают, например, 0-day.

  • Третьи просят сдавать все сразу.

Если проигнорировать эти условия, ваш отчет может остаться без ответа или быть отклонен. У меня был такой случай в одной из программ на площадке Standoff: я воспроизвел CVE в GitLab, эксплойт отработал на публичном инстансе, но из-за несоблюдения правил программы награда мне не досталась. Нужно было ждать около двух недель после выхода CVE, а я отправил сразу, с желанием сделать компанию безопаснее.

Также стоит задуматься о сроках репортинга. Это вопрос дискуссионный, ведь злоумышленники не ждут, а каждый день промедления увеличивает риски для пользователей.

Вот, пожалуй, всё, что пригодится начинающим багхантить 1-day. Если будут вопросы по теме - с удовольствием отвечу в комментариях под статьёй. А пока - удачной охоты!