Форк репозитория — операция настолько привычная, что на нее редко смотрят с подозрением. Но что, если через обычный форк можно запустить произвольный код на CI/CD-воркере чужой приватной компании? 

Именно такую цепочку мы обнаружили в GitFlic — отечественной платформе для совместной разработки ПО и хранения исходного кода от компании «РеСолют». 

GitFlic во многом похож на GitLab — что логично, ведь создавался как его альтернатива. И получилось у разработчиков сносно: если вы работали с GitLab, то GitFlic вызовет у вас приятное чувство дежавю.

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

Обнаруженные нами уязвимости были оперативно исправлены разработчиками компании «РеСолют» и зарегистрированы в БДУ ФСТЭК: BDU:2025-12462, BDU:2025-12463, BDU:2025-12464.


Первая находка: форк без проверки прав 

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

Именно с контроля доступа мы и начали смотреть на GitFlic. Итак, вниманию читателей представляется данный запрос:

Что же тут происходит? Форк репозитория. Операция вполне обычная для git-систем, однако есть один нюанс — поле «owner» контролирует пользователь
Что же тут происходит? Форк репозитория. Операция вполне обычная для git-систем, однако есть один нюанс — поле «owner» контролирует пользователь

Обычно при форке мы создаем копию репозитория «для себя». Но в сложных корпоративных сценариях бывает нужно форкнуть не себе, а в пространство команды или компании. Так что сам факт того, что пользователь может указать owner’а — не баг, а вполне нормальное явление. А вот вопрос того, как проверяются права, связанные с тем значением, которое мы передали, весьма критичен.

Какие вопросы должна задать система:

  1. Имеет ли пользователь доступ к репозиторию?

  2. Можно ли форкать репозиторий?

  3. Имеет ли пользователь права на форк репозитория?

  4. Имеет ли пользователь права на целевую сущность (пользователь, команда, компания), в которую будет скопирован репозиторий?

Список можно дополнять на свой вкус и цвет, но мы привели наиболее важные вопросы. И увы, но GitFlic не задал вопрос №4. К чему это может привести? 

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

Дополняет эту проблему еще и то, что у такого форка появляются два полноправных владельца: тот, кто инициировал форк, и тот, кому он формально принадлежит. Проще говоря, у создаваемого репозитория оказывается два поля: «creator» и «owner». Причем права у обоих — равные и полные. В интерфейсе это отображается кривовато, но с точки зрения системы оба могут делать с репозиторием все что угодно.

Звучит как неплохая заготовка для социальной инженерии: создать «троянского коня» среди репозиториев компании, а потом ждать, пока кто-то из разработчиков его скопирует и запустит. Мир уже видел примеры подобных атак, затрагивающих средства локальной разработки, эксплойты для таких сценариев есть в свободном доступе. Однако подобные атаки прямо зависят от поведения и состава инфраструктуры потенциальной жертвы. Из-за данных ограничений уязвимость изначально получила «низкую» критичность. 

Всё-таки это крит

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

Во многом унаследовав от GitLab структуру CI/CD, система получила ряд улучшений в части изоляции и распределения воркеров. В GitFlic реализована более гибкая модель: воркеры можно привязывать не к репозиториям, а к сущностям верхнего уровня — пользователям, командам или компаниям. Теперь воркеры не лежат в общем пуле, которым управляет один только админ, а каждый сам решает, нужен ли им воркер и что он будет делать. 

При более детальном разборе этой фичи был обнаружен интересный парадокс: механизм, позволяющий сделать систему более гибкой и безопасной, превращает уязвимость, которая казалась пригодной лишь для социалки или шалостей, в серьезный инструмент для атак на среду разработки или на всю цепочку разработки в целом. Как же это будет выглядеть?

Представим, что есть некая компания «priv-comp». У нее закрытые проекты, разработчики, настроенный CI/CD. И, что важно, — собственный приватный воркер, подключенный на уровне компании. По умолчанию такой воркер будет обслуживать все CI/CD-задачи проектов, принадлежащих компании. Команда приватная, проекты не видны извне, доступ только по приглашениям. Сценарий типичен для рынка, где уйма проектов реализуется подрядчиками.

риватная компания «priv-comp» с подключенным приватным воркером для CI/CD
риватная компания «priv-comp» с подключенным приватным воркером для CI/CD

И есть теоретический злоумышленник «test», проникнувший в наш GitFlic. Украл ли он чей-то пароль или воспользовался неотключенной регистрацией, не суть важно. Первым своим действием он подготовит «троянского коня» — репозиторий с конфигурацией для CI/CD.

Репозиторий пользователя test с конфигурацией для CI/CD 
Репозиторий пользователя test с конфигурацией для CI/CD 

Приведенный пример CI/CD конфигурации — простой, академический, но вполне отражает суть действий. При выполнении такого конфига будет исполнена команда уровня ОС на подключенном воркере. Далее же произойдет именно то, о чем мы говорили ранее: форк созданного «троянского коня» в компанию «priv-comp».

Результат для пользователя «test» будет выглядеть так:

Созданный форк «троянского коня» в компании «priv-comp»
Созданный форк «троянского коня» в компании «priv-comp»

Помните часть про особенности привилегий у создаваемого форка, там, где было сказано про равные права «owner» и «creator»? Так вот «равность и полнота» прав на репозиторий включает в себя возможность запуска CI/CD конвейера. Т. е. пользователь «test» может просто взять и запустить пайплайн в созданном форке, который будет обработан воркером компании «priv-comp».

Собственно, сам результат:

Произвольный код успешно выполнился на воркере компании «priv-comp». Атаку можно считать успешной.

Вместо заключения

Целью этой статьи было не столько рассказать про найденную уязвимость, а, скорее, показать ход наших размышлений при изучении систем.

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

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

P. S. Тем, кто дочитал до конца

Для самых внимательных читателей, которые уже собирались задать резонный вопрос: «А как злоумышленник узнает имена приватных компаний, чтобы форкнуть репозиторий? Они же приватные, их в интерфейсе не видно».

Что ж, мы нашли несколько уязвимостей, некоторые из них работают в связке. В качестве бонуса и приглашения к самостоятельному исследованию подскажем направление:

/api/search/company

Исследуйте этот эндпоинт. Там вас ждет пара небольших, но познавательных сюрпризов. 😉


PURP — Telegram-канал, где кибербезопасность раскрывается с обеих сторон баррикад

t.me/purp_sec — инсайды и инсайты из мира этичного хакинга и бизнес-ориентированной защиты от специалистов Бастиона