В ходе проектов по пентесту и программ Bug Bounty специалисты по ИБ часто сталкиваются с GitLab, но они не одиноки — злоумышленники тоже не упускают возможности завладеть секретами репозиториев или даже исполнить код на сервере. В новой статье приоткроем завесу тайн GitLab через функционал Explore, покажем интересные кейсы из Bug Bounty и пентестов, где небольшая мисконфигурация приводит к тяжелым последствиям.
Меня зовут Дмитрий Прохоров, я пентестер из команды CyberOK. Часто на проектах по пентесту, а также в программах Bug Bounty встречаются Gitlab-ы. И встречаются они не только специалистам по ИБ, но и злобным хакерам, которые не прочь завладеть секретами репозиториев и даже исполнить код на сервере! Все представленные материалы несут образовательный характер J
Сегодня я бы хотел посвятить свой монолог тем, кто любит приоткрывать завесу тайн своего Gitlab через функционал Explore и показывать интересные кейсы из Bug Bounty и пентестов, где небольшая мисконфигурация приводит к тяжелым последствиям.
Холивар на тему функционала исследования Gitlab для анонимных пользователей тянулся несколько лет с 2017 года. И закрытие данной фичи до 2020 года являлось скорее костылем. Но на проблему обратили внимание и все-таки закрыли Explore и Help для неаутентифицированных пользователей через настройки видимости репозитория (Covid сыграл в этом некую роль).
Рис.1 GitHub
Поэтому речь, по большому счету, пойдет о тех организациях, где уровень видимости настроен некорректно и дает злобным хакерам больше информации, чем нужно.
Введение прошло, переходим к исследованию. Самое очевидное, что стоит поискать в Gitlab — это токены, API-ключи и информацию о внутренней сети.
В проектах встречалось разное J:
Рис. 2 Раскрытие логина и пароля Gitlab (https://login:pass@gitlab.example.com). Автор: Д. В. Прохоров, 2024.
Рис. 3 Раскрытие логина и пароля БД в файле .sh. Автор: Д. В. Прохоров, 2024.
Рис. 4 Раскрытие ключей API в файле .sh. Автор: Д. В. Прохоров, 2024.
Рис. 5 Раскрытие окружения Shared Runner в файле. yml – Ansible. Автор: Д. В. Прохоров, 2024.
И если, рассматривая первые три скриншота, все вполне очевидно (и ничего нового я не показал), то окружение Shared Runner-а представляет наибольший интерес для эксплуатации связки уязвимостей и выполнения удаленного кода на сервере. При наличии раскрытия токена Shared Runner-а мы можем обратиться напрямую к Gitlab и перехватить сессию задач процесса CI/CD. Это может помочь получить первоначальный доступ к репозиторию от имени пользователя проекта.
Что ж, если на различные токены и секреты репозиторий пуст, то идем в раздел CI/CD проекта и смотрим, что там в Jobs’ах:
Рис. 6 Еще одно место для утечек переменных окружения. Автор: Д. В. Прохоров, 2024.
Наличие процессов CI/CD — это уже хорошо и здесь можно выстроить интересный вектор, о котором очень подробно рассказали ребята из Pulse Security.
И именно этот вектор позволил мне попасть в шорт-лист Pentest Award, а также забрать хорошую баунти в одной из программ VK.
Главной проблемой был доступ к данному репозиторию. К сожалению, утечки токена Shared Runner’а не было, но мы как хитрые багхантеры знаем, что при возможности приобретения легального доступа (да-да, не Try Harder) не жалко вложить собственные средства, которые с большей вероятностью окупятся. И это был именно такой случай. Немного заморочившись с вводом данных своей карты, я получил заветные креды и побежал проверять свою теорию похека J.
Моя теория заключалась в следующем. Shared Runners в Gitlab — это составляющая процесса Pipeline среды CI/CD.
Рис.7
Для хакера это лакомый кусочек в случае, если:
1) Пользователь имеет право на запись в .gitlab_ci.yml в репозитории;
2) Runner находится во внутренней инфраструктуре.
По умолчанию GitLab Runners доступны для каждого проекта. Это означает, что злоумышленнику не требуется доступ к определенному репозиторию для проведения атак. Злоумышленник, имеющий любой доступ к GitLab, может создать личный репозиторий и начать атаковать инфраструктуру раннера.
Рис. 8
Более того, как правило, для этого используется «docker-in-docker» (DIND) для создания контейнера внутри конвейера (Pipeline).
По указанной выше схеме-картинке, в качестве одноглазого Джо, я прошелся, изучая CI/CD на сервере Gitlab.
Немного пройдясь по проектам злополучного репозитория, забрав шаблонный .gitlab_ci.yml и удалив оттуда все лишнее, я собрал такой вот джентельменский набор буковок:
Рис.9 Автор: Д. В. Прохоров, 2024.
Перед тем как проводить манипуляции, важно клацнуть на раннер, который нам нужен в настройках CI/CD репозитория.
Поднимаем на своей Front Gun пушке nc:
Рис.10 Автор: Д. В. Прохоров, 2024.
Запускаем билд и ждем прилета нашего бэкконнекта.
Рис.11 Автор: Д. В. Прохоров, 2024.
И мы в докере. Полученный shell кривой и неудобный. Поэтому получаем хороший TTY (как же тут без табов и .bash_history):
apt update apt install python3 python3 -c 'import pty; pty.spawn("/bin/bash")' # Ctrl+Z stty raw -echo; fg; ls; export SHELL=/bin/bash; export TERM=screen; stty rows 38 columns 116; reset;
И вот мы гуляем по среде Shared Runner’a. Конечно, нам от него никакого импакта, кроме как возможных билдов других пользователей. Но мы же в докере, а значит нужно повышаться до докер-хоста.
И в моем кейсе все прошло достаточно тривиально :)
Заходим в /var и видим по дефолту лежащий docker.sock.
Рис.12 Автор: Д. В. Прохоров, 2024.
Тут у меня глаза загорелись! Настраиваем среду для запуска docker-ce:
apt install apt-transport-https ca-certificates curl software-properties-common -y curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" apt update apt install docker-ce -y
И вводим заветную команду для профита:
docker run -it --privileged -v /:/host/ ubuntu bash -c "chroot /host/"
Рис. 13 Автор: Д. В. Прохоров, 2024.
Забегаю с рутом посмотреть, а что там в /home и наблюдаю пользователей инфры.
Рис.14 Автор: Д. В. Прохоров, 2024.
Счастью не было предела и отчет начал писаться под выброс легкого адреналин). Отдельная благодарность команде VK за быстрый триаж и отличную выплату!
Для полного понимания вышеуказанной цепочки различных мисконфигураций и уязвимостей можно привести следующую схему:
Рис.15
Возращаясь ко второму заголовку: «Explore – не баг, а фича!», стоит отметить, что данный функционал, доступный анонимному пользователю – это все-таки баг. Отслеживать все процессы и пуши, происходящие в Gitlab, а также то, какие данные будут доступны «случайному» пользователю, крайне сложно. Поэтому стоит серьёзно отнестись к настройке приватности вашего репозитория.
По данным нашей «кибербалайки» СКИПА на текущий момент в Рунете развернуто 14798 инстансов с Gitlab из которых 3263 имеют включенный функционал Explore для анонимных пользователей, что потенциально говорит о возможной утечке чувствительных данных.
Рис.16 Автор: Д. В. Прохоров, 2024.
Давайте делать наш Рунет безопаснее!
Гравитация научных фактов сильнее, чем вы думаете