Concourse Enumeration & Attacks
Concourse Enumeration & Angriffe
Benutzerrollen & Berechtigungen
Concourse wird mit fünf Rollen geliefert:
Concourse Admin: Diese Rolle wird nur den Besitzern des Hauptteams (Standard-Initialteam von Concourse) zugewiesen. Admins können andere Teams konfigurieren (z. B.:
fly set-team
,fly destroy-team
...). Die Berechtigungen dieser Rolle können nicht durch RBAC beeinflusst werden.Besitzer: Team-Besitzer können alles innerhalb des Teams ändern.
Mitglied: Teammitglieder können innerhalb der Team-Ressourcen lesen und schreiben, können jedoch die Team-Einstellungen nicht ändern.
Pipeline-Betreiber: Pipeline-Betreiber können Pipeline-Vorgänge wie das Auslösen von Builds und das Anheften von Ressourcen durchführen, können jedoch keine Pipeline-Konfigurationen aktualisieren.
Viewer: Team-Viewer haben "nur-Lese" Zugriff auf ein Team und dessen Pipelines.
Darüber hinaus können die Berechtigungen der Rollen Besitzer, Mitglied, Pipeline-Betreiber und Viewer geändert werden, indem RBAC konfiguriert wird (indem die Aktionen spezifischer konfiguriert werden). Lesen Sie mehr darüber unter: https://concourse-ci.org/user-roles.html
Beachten Sie, dass Concourse Pipelines innerhalb von Teams gruppiert. Daher können Benutzer, die einem Team angehören, diese Pipelines verwalten, und mehrere Teams können existieren. Ein Benutzer kann mehreren Teams angehören und in jedem von ihnen unterschiedliche Berechtigungen haben.
Vars & Credential Manager
In den YAML-Konfigurationen können Werte mit der Syntax ((_source-name_:_secret-path_._secret-field_))
konfiguriert werden.
Aus den Dokumenten: Der Quellname ist optional, und wenn er weggelassen wird, wird der clusterweite Credential-Manager verwendet, oder der Wert kann statisch bereitgestellt werden.
Das optionale _secret-field_ gibt ein Feld im abgerufenen Geheimnis an, das gelesen werden soll. Wenn es weggelassen wird, kann der Credential-Manager wählen, ein 'Standardfeld' aus dem abgerufenen Credential zu lesen, wenn das Feld existiert.
Darüber hinaus können secret-path und secret-field von doppelten Anführungszeichen "..."
umgeben sein, wenn sie Sonderzeichen wie .
und :
enthalten. Zum Beispiel wird ((source:"my.secret"."field:1"))
den secret-path auf my.secret
und das secret-field auf field:1
setzen.
Statische Vars
Statische Vars können in Aufgabenschritten angegeben werden:
Argumente
Oder verwenden Sie die folgenden fly
Argumente:
-v
oder--var
NAME=VALUE
setzt den StringVALUE
als Wert für die VariableNAME
.-y
oder--yaml-var
NAME=VALUE
analysiertVALUE
als YAML und setzt es als Wert für die VariableNAME
.-i
oder--instance-var
NAME=VALUE
analysiertVALUE
als YAML und setzt es als Wert für die InstanzvariableNAME
. Weitere Informationen zu Instanzvariablen finden Sie unter Gruppierung von Pipelines.-l
oder--load-vars-from
FILE
lädtFILE
, ein YAML-Dokument, das Zuordnungen von Variablennamen zu Werten enthält, und setzt sie alle.
Credential Management
Es gibt verschiedene Möglichkeiten, wie ein Credential Manager in einer Pipeline angegeben werden kann, lesen Sie dazu unter https://concourse-ci.org/creds.html. Darüber hinaus unterstützt Concourse verschiedene Credential Manager:
Beachten Sie, dass wenn Sie Schreibzugriff auf Concourse haben, Sie Jobs erstellen können, um diese Geheimnisse abzuschöpfen, da Concourse darauf zugreifen können muss.
Concourse Enumeration
Um eine Concourse-Umgebung aufzulisten, müssen Sie zunächst gültige Anmeldeinformationen sammeln oder einen authentifizierten Token wahrscheinlich in einer .flyrc
-Konfigurationsdatei finden.
Anmeldung und aktueller Benutzerenum
Um sich anzumelden, müssen Sie den Endpunkt, den Teamnamen (Standard ist
main
) und ein Team, dem der Benutzer angehört, kennen:fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]
Erhalten Sie konfigurierte Ziele:
fly targets
Überprüfen Sie, ob die konfigurierte Zielverbindung noch gültig ist:
fly -t <target> status
Erhalten Sie die Rolle des Benutzers gegenüber dem angegebenen Ziel:
fly -t <target> userinfo
Beachten Sie, dass das API-Token standardmäßig in $HOME/.flyrc
gespeichert wird. Wenn Sie Maschinen plündern, könnten Sie dort die Anmeldeinformationen finden.
Teams & Benutzer
Erhalten Sie eine Liste der Teams
fly -t <target> teams
Erhalten Sie Rollen innerhalb des Teams
fly -t <target> get-team -n <team-name>
Erhalten Sie eine Liste der Benutzer
fly -t <target> active-users
Pipelines
Auflisten von Pipelines:
fly -t <target> pipelines -a
Abrufen von Pipeline-YAML (sensible Informationen könnten in der Definition gefunden werden):
fly -t <target> get-pipeline -p <pipeline-name>
Erhalten Sie alle in der Pipeline deklarierten Konfigurationsvariablen
for pipename in $(fly -t <target> pipelines | grep -Ev "^id" | awk '{print $2}'); do echo $pipename; fly -t <target> get-pipeline -p $pipename -j | grep -Eo '"vars":[^}]+'; done
Erhalten Sie alle verwendeten geheimen Namen der Pipelines (wenn Sie einen Job erstellen/ändern können oder einen Container kapern können, könnten Sie sie abgreifen):
Container & Worker
Liste Worker:
fly -t <Ziel> workers
Liste Container:
fly -t <Ziel> containers
Liste Builds (um zu sehen, was läuft):
fly -t <Ziel> builds
Concourse Angriffe
Anmeldeinformationen Brute-Force
admin:admin
test:test
Geheimnisse und Parameter Enumeration
Im vorherigen Abschnitt haben wir gesehen, wie Sie alle Geheimnisnamen und Variablen erhalten können, die von der Pipeline verwendet werden. Die Variablen können sensible Informationen enthalten und der Name der Geheimnisse wird später nützlich sein, um zu versuchen, sie zu stehlen.
Sitzung innerhalb eines laufenden oder kürzlich ausgeführten Containers
Wenn Sie ausreichende Berechtigungen haben (Mitgliedsrolle oder höher), können Sie Pipelines und Rollen auflisten und einfach eine Sitzung innerhalb des <Pipeline>/<Job>
Containers erhalten, indem Sie:
Mit diesen Berechtigungen könnten Sie möglicherweise:
Die Geheimnisse innerhalb des Containers stehlen
Versuchen, auf den Knoten zu entkommen
Cloud-Metadaten-Endpunkt aufzählen/missbrauchen (vom Pod und vom Knoten aus, wenn möglich)
Pipeline-Erstellung/Änderung
Wenn Sie ausreichende Berechtigungen haben (Mitgliedsrolle oder höher), können Sie neue Pipelines erstellen/ändern. Überprüfen Sie dieses Beispiel:
Mit der Änderung/Erstellung einer neuen Pipeline können Sie Folgendes tun:
Geheimnisse stehlen (indem Sie sie ausgeben oder in den Container gelangen und
env
ausführen)Zum Knoten entkommen (indem Sie ausreichend Berechtigungen erhalten -
privileged: true
)Cloud-Metadaten-Endpunkt aufzählen/missbrauchen (vom Pod und vom Knoten aus)
Die erstellte Pipeline löschen
Benutzerdefinierte Aufgabe ausführen
Dies ist ähnlich wie die vorherige Methode, aber anstatt eine ganz neue Pipeline zu ändern/zu erstellen, können Sie einfach eine benutzerdefinierte Aufgabe ausführen (was wahrscheinlich viel unauffälliger sein wird):
Entkommen zum Knoten aus privilegierter Aufgabe
In den vorherigen Abschnitten haben wir gesehen, wie man eine privilegierte Aufgabe mit Concourse ausführt. Dies gibt dem Container nicht genau den gleichen Zugriff wie das privilegierte Flag in einem Docker-Container. Zum Beispiel sehen Sie das Knoten-Dateisystemgerät nicht in /dev, daher könnte die Flucht "komplexer" sein.
Im folgenden PoC werden wir den release_agent verwenden, um mit einigen kleinen Modifikationen zu entkommen:
Wie Sie vielleicht bemerkt haben, handelt es sich hierbei nur um einen regulären release_agent escape, bei dem lediglich der Pfad des Befehls im Knoten geändert wird.
Entkommen zum Knoten aus einem Worker-Container
Ein regulärer release_agent escape mit einer geringfügigen Änderung ist ausreichend:
Entkommen zum Knoten aus dem Web-Container
Auch wenn die Web-Container einige Verteidigungen deaktiviert haben, läuft er nicht als ein gewöhnlicher privilegierter Container (zum Beispiel kannst du nicht mounten und die Fähigkeiten sind sehr begrenzt, daher sind alle einfachen Wege, um aus dem Container auszubrechen, nutzlos).
Es speichert jedoch lokale Anmeldeinformationen im Klartext:
Du könntest diese Anmeldeinformationen verwenden, um dich am Webserver anzumelden und einen privilegierten Container zu erstellen und auf den Knoten zu entkommen.
In der Umgebung findest du auch Informationen zum Zugriff auf die PostgreSQL-Instanz, die Concourse verwendet (Adresse, Benutzername, Passwort und Datenbank sowie andere Informationen):
Ausnutzung des Garden-Dienstes - Kein echter Angriff
Dies sind nur einige interessante Notizen über den Dienst, aber da er nur auf localhost lauscht, werden diese Notizen keine Auswirkungen haben, die wir nicht bereits zuvor ausgenutzt haben.
Standardmäßig wird jeder Concourse-Worker einen Garden-Dienst auf Port 7777 ausführen. Dieser Dienst wird vom Web-Master verwendet, um dem Worker mitzuteilen, was er ausführen muss (das Bild herunterladen und jede Aufgabe ausführen). Das klingt ziemlich gut für einen Angreifer, aber es gibt einige gute Schutzmaßnahmen:
Es ist nur lokal freigegeben (127.0.0.1) und ich denke, wenn der Worker sich erneut beim Web mit dem speziellen SSH-Dienst authentifiziert, wird ein Tunnel erstellt, damit der Webserver mit jedem Garden-Dienst innerhalb jedes Workers kommunizieren kann.
Der Webserver überwacht die laufenden Container alle paar Sekunden, und unerwartete Container werden gelöscht. Wenn Sie also einen benutzerdefinierten Container ausführen möchten, müssen Sie die Kommunikation zwischen dem Webserver und dem Garden-Dienst manipulieren.
Concourse-Worker werden mit hohen Containerberechtigungen ausgeführt:
Jedoch werden Techniken wie das Einbinden des /dev-Geräts des Knotens oder release_agent nicht funktionieren (da das echte Gerät mit dem Dateisystem des Knotens nicht zugänglich ist, sondern nur ein virtuelles). Wir können nicht auf Prozesse des Knotens zugreifen, daher wird die Flucht aus dem Knoten ohne Kernel-Exploits kompliziert.
Im vorherigen Abschnitt haben wir gesehen, wie man aus einem privilegierten Container fliehen kann. Wenn wir also Befehle in einem von dem aktuellen Worker erstellten privilegierten Container ausführen können, könnten wir zum Knoten fliehen.
Beachten Sie, dass ich beim Experimentieren mit Concourse festgestellt habe, dass, wenn ein neuer Container erstellt wird, um etwas auszuführen, die Containerprozesse aus dem Worker-Container zugänglich sind. Es ist also, als ob ein Container einen neuen Container in seinem Inneren erstellt.
Zugriff auf einen laufenden privilegierten Container
Erstellen eines neuen privilegierten Containers
Sie können sehr einfach einen neuen Container erstellen (einfach eine zufällige UID ausführen) und etwas darauf ausführen:
Jedoch überprüft der Webserver alle paar Sekunden die laufenden Container, und wenn ein unerwarteter entdeckt wird, wird er gelöscht. Da die Kommunikation über HTTP erfolgt, könnten Sie die Kommunikation manipulieren, um die Löschung unerwarteter Container zu vermeiden:
Referenzen
https://concourse-ci.org/vars.html
Last updated