
CVE-2020-13277 Cyber Range: Gitlab-Logikschwachstelle - Unbefugter Zugriff beliebiger Benutzer auf private Repositories
CVE-2020-13277 Übungsfeld: Gitlab Logik-Schwachstelle – Unbefugter Zugriff auf private Repositories durch beliebige Benutzer
CVE-2020-13277
├── README.md ............... [Diese README-Datei]
├── imgs .................... [Bilder zur Unterstützung der README]
├── gitlab .................. [Einhängeverzeichnis des Gitlab-Containers]
│ ├── Dockerfile .......... [Docker-Build-Datei für Gitlab]
│ ├── config .............. [Einhängeverzeichnis für Gitlab-Konfiguration]
│ ├── data ................ [Einhängeverzeichnis für Gitlab-Daten]
│ ├── logs ................ [Einhängeverzeichnis für Gitlab-Logs]
│ ├── keys ................ [Speicherverzeichnis für den geknackten Gitlab-Lizenzschlüssel]
│ └── runner .............. [Einhängeverzeichnis des Runner-Containers]
├── license ................. [Build-Verzeichnis des Containers für die Lizenz]
│ ├── Dockerfile .......... [Docker-Build-Datei für die Lizenz]
│ └── license.rb .......... [Ruby-Skript zum Generieren der geknackten Lizenz]
├── docker-compose.yml ...... [Docker-Build-Konfiguration]
├── keygen.ps1 .............. [Windows: Lizenz mit einem Klick generieren]
├── keygen.sh ............... [Linux: Lizenz mit einem Klick generieren]
├── run.ps1 ................. [Windows: Gitlab-Übungsfeld mit einem Klick starten]
├── run.sh .................. [Linux: Gitlab-Übungsfeld mit einem Klick starten]
├── register.ps1 ............ [Windows: Runner mit einem Klick registrieren]
├── register.sh ............. [Linux: Runner mit einem Klick registrieren]
├── stop.ps1 ................ [Windows: Gitlab-Übungsfeld mit einem Klick stoppen]
└── stop.sh ................. [Linux: Gitlab-Übungsfeld mit einem Klick stoppen]
Diese Schwachstelle nutzt hauptsächlich die Mirror Repository – die Funktion zur Spiegelung und Synchronisation von Repository-Backups.
Die Spiegelungsrichtung von Mirror unterteilt sich in zwei Typen:
Die Schwachstelle nutzt die Mirror-Repository-Pull-Richtung
Es ist bekannt, dass Gitlab in zwei Editionen unterteilt ist: CE (Community Edition, kostenlos) und EE (Enterprise Edition, kostenpflichtig). Gitlab gibt offiziell an, dass diese Schwachstelle die folgenden Versionen von CE und EE betrifft:
>=10.6, <12.9.10>=12.10, <12.10.11>=13.0, <13.0.6Das bedeutet jedoch nicht, dass alle diese Versionen des Gitlab Docker-Images zum Aufbau des Übungsfelds verwendet werden können, da:
Mit anderen Worten: Um das Übungsfeld mit Docker aufzubauen, kann nur die Gitlab-EE-Version verwendet werden, die dann geknackt werden muss (Wohlhabende können auch eine Lizenz kaufen), um die Mirror-Repository-Pull-Funktion zu aktivieren.
Aber selbst nach dem Knacken von Gitlab-EE wird bei den Versionen 10.x, oder beim Einfügen einer lokalen Pfad-URL in Mirror Repository - Pull ein Fehler ausgegeben: . Obwohl man über die Option aktivieren kann, um lokale URLs zu konfigurieren, tritt beim Synchronisieren des Spiegels der Fehler auf. Das bedeutet, dass nur das Ziehen von Remote-Repositorys funktioniert.
./keygen.sh oder ./keygen.ps1./run.sh oder ./run.ps1Beim vorherigen Generieren des geknackten Schlüsselpaars wurde der öffentliche Schlüssel bereits im Hintergrund in den Gitlab-Container geschrieben. Der private Schlüssel muss noch über das Frontend in Gitlab hochgeladen werden, um das Knacken abzuschließen:
./gitlab/keys/ generiert; den Inhalt der darin enthaltenen .gitlab-license (privater Schlüssel) kopierenEnter license key auswählen, den privaten Schlüssel einfügen und auf die Schaltfläche Upload license klicken, um das Knacken abzuschließenDamit ist die Mirror-Repository-Pull-Funktion aktiviert

Outbound requests finden, die Option Allow requests to the local network from hooks and services aktivieren und speichernDamit unterstützt Mirror Repository - Pull nun das Abrufen lokaler Repositorys

./register.sh $TOKEN oder ./register.ps1 $TOKENDamit können alle Repositorys diesen Runner zur Ausführung von CI-Skripten (Pipeline Jobs) verwenden

Der Validierungsprozess kann sich an der offiziellen Issue orientieren, aber der folgende Validierungsprozess wird in diesem Übungsfeld einige Schritte leicht anpassen
Mit dem Benutzer root die Seite http://127.0.0.1/admin/users öffnen und 3 Konten erstellen:
victim: Opferkontoattacker1: Angreiferkonto 1attacker2: Angreiferkonto 2Beim Erstellen eines Kontos kann kein initiales Passwort festgelegt werden. Gitlab sendet standardmäßig ein initiales Passwort an die angegebene E-Mail. Der Einfachheit halber kann man eine beliebige E-Mail-Adresse eingeben, das Konto erstellen und dann sofort bearbeiten. In diesem Fall kann man mit root das initiale Passwort für das Konto festlegen, ohne auf die E-Mail angewiesen zu sein.

victim bei Gitlab anmeldenNew Project erstellen:
targetPrivateREADME.md erstellen und einen beliebigen Inhalt wie mykey is abcxyz eingebenOffensichtlich ist
targetdas private Repository vonvictim, und unser Ziel ist es, durch die Schwachstelle den Inhalt dieses Repositorys zu erlangen

attacker1 bei Gitlab anmeldenNew Project erstellen:
pocPublic.gitlab-ci.yml mit folgendem Inhalt erstellen:image: "ruby:2.6"
rspec:
script:
- git clone http://gitlab-ci-token:[email protected]/victim/target.git
- cd target
- ls -lah .
- cat README.md
【Zweck】In den folgenden Schritten wird durch einige Tricks erreicht, dass victim ohne Wissen unter Verwendung seiner Berechtigungen dieses CI-Skript ausführt.
Da dieses Übungsfeld keine Zertifikate einrichtet, kann nur das
http-Protokoll verwendet werden; außerdem ist172.168.30.2die IP, diedocker-compose.ymldem Gitlab-Container zuweist. Da dieses CI-Skript letztendlich über den Runner ausgeführt wird und der Runner und Gitlab in diesem Übungsfeld nicht derselbe Container sind, muss die vom Docker zugewiesene IP-Adresse verwendet werden

attacker2 bei Gitlab anmeldenNew Group erstellen:
testPublictest ein neues, völlig leeres Repository New Project erstellen:
pocPublic
Spiegel-Repository konfigurieren Settings => Repository => Pull from a remote repository:
Mirror repository: aktivierenGit repository URL: http://GITLAB/attacker1/poc eingebenPassword: (leer lassen, da das zu pullende Repository öffentlich ist, kein Passwort erforderlich)Trigger pipelines for mirror updates: aktivieren (Auslösen der CI-Skriptausführung bei Spiegel-Synchronisation)Nach erfolgreicher Konfiguration wird alle 30 Minuten überprüft, ob sich das Quell-Repository geändert hat. Wenn ja, wird eine erzwungene Synchronisation durchgeführt.
Die
Git repository URLzeigt auf das zuvor erstellte PoC-Repository. Der Grund, warum nicht 127.0.0.1 verwendet wird, liegt darin, dass das Abrufen lokaler Repositorys verboten ist, aber die DNS-Umgehung genutzt werden kann:GITLABist der Hostname, der dem Gitlab-Container indocker-compose.ymlzugewiesen wird. Standardmäßig wird er in/etc/hostseingetragen. Obwohl der HostGITLABnicht auflösen kann, entspricht dies innerhalb des Containers dem Zugriff aufhttp://127.0.0.1/attacker1/poc

attacker2 arbeitentest zu verwaltenvictim zur Gruppe hinzufügen:
Add new member to test: victimPermissions: OwnerExpiration date: (leer lassen, d.h. unbegrenzt)=> Setting => Account => Delete account, um das aktuelle Konto (attacker2) zu löschen【Zweck】In der Gruppe test gibt es nur zwei Owner: victim und attacker2. Wenn der Benutzer attacker2 gelöscht wird, wird der Besitz der Gruppe test und aller darunter liegenden Repositorys zwangsweise an victim übertragen. Da es in der Gruppe test derzeit ein von attacker1/poc gespiegeltes Repository test/poc gibt, wird das Repositorium test/poc effektiv zwangsweise an den Benutzer victim vererbt.


Zunächst der aktuelle Stand:
victim ein Repository test/poc erstellttest/poc wird vom Repository attacker1/poc gespiegelt (alle 30 Minuten wird geprüft, ob sich etwas geändert hat und synchronisiert werden muss)attacker1/poc wird vom Angreifer kontrolliert, einschließlich des CI-Skripts .gitlab-ci.ymltest/poc die Option Trigger pipelines for mirror updates aktiviert hat, wird bei jeder Synchronisation das CI-Skript ausgeführtOwner von test/poc victim ist, wird das CI-Skript mit den Berechtigungen von victim ausgeführt
Zurück zum Inhalt des zuvor festgelegten CI-Skripts .gitlab-ci.yml: Dieses PoC greift im Runner mit den Berechtigungen von victim auf die Verzeichnisstruktur und die Datei README.md seines privaten Repositorys target zu:
image: "ruby:2.6"
rspec:
script:
- git clone http://gitlab-ci-token:[email protected]/victim/target.git
- cd target
- ls -lah .
- cat README.md
Anschließend muss der Angreifer nur beliebige unwichtige Änderungen am Repository attacker1/poc vornehmen. Im schlimmsten Fall muss er nur 30 Minuten warten, um dann das festgelegte CI-Skript mit den Berechtigungen von victim ausführen zu lassen.
Obwohl der Angreifer keine direkte Berechtigung hat, die Ergebnisse der Pipeline Jobs einzusehen, kann er durch Anpassen des Ausgabeziels des Skripts, z.B. durch Senden des Repository-Inhalts an eine bestimmte E-Mail oder einen FTP-Server, den Code des Repositorys stehlen.

12.x13.xImport url is blocked: Requests to localhost are not allowedAdmin area => Settings => Network => Outbound requestsAllow requests to the local network from hooks and services2:Fetching remote upstream failed: fatal: unable to access http://127.0.0.1/xxxx/: The requested URL returned error: 301Glücklicherweise sind die Überprüfungsmethoden für lokale URLs in den Versionen 12.x und 13.x sehr streng, aber in der Version 10.x gibt es einen Weg: Bei der Konfiguration der Pull-URL kann man einfach den Namen des lokal eingerichteten DNS-Dienstes verwenden, um eine Umgehung zu erreichen.
Zusammenfassend kann letztendlich nur das Docker-Image der Version gitlab-ee:10.6.0-ee.0 für den Aufbau dieses Übungsfelds verwendet werden.
Aus der vorherigen Beschreibung ist auch ersichtlich, dass die Ausnutzungsbedingungen dieser Schwachstelle relativ streng sind. Grundsätzlich ist es für arme Leute schwierig, von dieser Schwachstelle betroffen zu sein.