1 Punkte von GN⁺ 2025-04-01 | 1 Kommentare | Auf WhatsApp teilen
  • Wenn ein offengelegtes GITHUB_TOKEN in seinem kurzen Gültigkeitsfenster ausgenutzt wurde, konnte sich dadurch ein Angriffsweg für einen Lieferkettenangriff öffnen, der in mehreren Repositories mit CodeQL über GitHub-Actions-Workflows zur Codeausführung führen konnte
  • Das Token befand sich in einem Workflow-Artefakt, das von einem fehlgeschlagenen Debug-Workflow des Repositories github/codeql-action hochgeladen worden war, und es handelte sich um ein GitHub-App-Installationstoken mit den Berechtigungen contents: write, actions: write, packages: write
  • Der Erfolg des Angriffs hing von einer Race Condition ab: Das Token musste nach dem Artefakt-Upload und vor dem Ende des Jobs heruntergeladen und genutzt werden; laut tatsächlichen Logs gelang dies in etwa 1,022 Sekunden, beobachtet wurden rund 2 Sekunden für Branch-Erstellung, Push von poc.txt und Tag-Erstellung
  • Da die Standardkonfiguration von CodeQL intern den v3-Tag von github/codeql-action ausführt und dieser Tag nicht unveränderlich war, hätten Angreifer durch das Verschieben des Tags auf einen bösartigen Commit auch Repositories treffen können, die den Standard-CodeQL-Workflow verwenden
  • GitHub reichte rund drei Stunden nach der Meldung einen PR ein, der den Upload von Debug-Artefakten deaktivierte, vergab CVE-2025-24362 und erklärte im Advisory, dass keine Hinweise auf eine Kompromittierung der Plattform oder Systeme gefunden wurden

Angriffspfad auf die CodeQL-Lieferkette ausgehend von einem öffentlichen Artefakt

  • Ein einziges offengelegtes Secret konnte zu einem potenziellen Lieferkettenangriff auf GitHub CodeQL führen
  • Das betreffende Secret war jeweils nur etwa 1,022 Sekunden gültig, doch innerhalb dieses Fensters konnten Angreifer die nötigen Schritte ausführen, um innerhalb eines GitHub-Actions-Workflows Code auszuführen
  • Der mögliche Wirkungsbereich reichte sowohl bis zu GitHub Cloud als auch zu GitHub Enterprise
  • Zu den möglichen Auswirkungen gehörten:
    • Abfluss von Quellcode aus privaten Repositories, die CodeQL verwenden
    • Diebstahl von GitHub-Actions-Secrets innerhalb von CodeQL-Workflow-Jobs
    • Codeausführung auf interner Infrastruktur, auf der CodeQL-Workflows laufen
    • Diebstahl von Secrets aus Workflows, die GitHub Actions Cache in CodeQL-nutzenden Repositories verwenden
  • Laut GitHub Advisory fand GitHub keine Hinweise auf eine Kompromittierung der Plattform oder Systeme

Wie das Secret entdeckt wurde

  • Verwendet wurde ein Actions Artifacts Secret Scanner, der GitHub-Actions-Workflow-Artefakte herunterlädt, rekursiv entpackt und mit Nosey Parker nach Secrets scannt
  • Die Funktion wurde in Chariot integriert und als Open Source über die Funktion Gato veröffentlicht
  • Nach einem Tag Scanning wurde im Artefakt des Repositories github/codeql-action ein Token gefunden
    • Das Zielartefakt war die ZIP-Datei my-debug-artifacts, die vom Workflow „PR Check – Debug artifacts after failure“ hochgeladen worden war
    • Nach dem Entpacken von my-db-java-partial.zip wurde in einem Crash-Report ein GitHub-Token erkannt, das mit ghs_ begann
    • Eine manuelle Prüfung ergab, dass es sich um ein GitHub-App-Installationstoken handelte, das in einer Datei mit Umgebungsvariablen des GitHub-Runners gespeichert war

Verknüpfung von GitHub Actions, Artefakten und CodeQL

  • GitHub Actions ist eine CI/CD-Plattform, die in YAML-Workflows definierte Aufgaben auf Runnern ausführt
  • Jeder Workflow-Run erzeugt ein automatisch generiertes GitHub-App-Installationstoken namens GITHUB_TOKEN
    • Der Runner authentifiziert sich damit bei GitHub, um die vom Workflow verlangten Aufgaben auszuführen
    • Die Berechtigungen können auf Workflow-, Repository- und Organisationsebene festgelegt werden
  • GitHub-Actions-Workflow-Artefakte sind Dateien, die ein Workflow zur späteren Verwendung in GitHub Actions speichert
    • Standardmäßig sind sie für Personen mit Leserechten auf das Repository zugänglich
    • Sie werden bis zu 90 Tage gespeichert
  • CodeQL ist GitHubs Engine für Codeanalyse und wird für statische Analysen in GitHub-Repositories zur Erkennung von Schwachstellen verwendet
  • Sicherheitstools wie CodeQL müssen teils auf sensible Systeme und Daten zugreifen und können bei einer Kompromittierung zu einer Backdoor werden

Token-Berechtigungen und Race Condition

  • Im Schritt „Setup Job“ der Workflow-Logs war zu sehen, dass das betreffende GITHUB_TOKEN volle Schreibrechte hatte
  • Besonders wichtig waren folgende Berechtigungen:
    • contents: write: Branches erstellen, Tags erstellen, Release-Artefakte hochladen
    • actions: write: Actions-Jobs und workflow_dispatch-Events auslösen
    • packages: write: Pakete hochladen
  • Da das Token nur während der Laufzeit des Workflow-Jobs gültig war, mussten für den Angriff drei Bedingungen erfüllt sein:
    • Das Token musste Schreibrechte haben
    • Es musste die Upload-Artifact-API v4 verwendet werden, mit der sich Artefakte vor Abschluss des Jobs abrufen lassen
    • Das Zeitfenster zwischen Artefakt-Upload und Job-Ende musste ausreichen, um das Token herunterzuladen, zu entpacken und zu nutzen
  • CodeQL verwendete die Action actions/upload-artifact nicht direkt, sondern nutzte im Quellcode manuell den Upload-Artifact-Client; laut Kommentar im Code kam Version 4 zum Einsatz
  • Die Zeitabstände in den rohen GitHub-Logs waren extrem kurz:
    • „Finalizing artifact upload“: 17:22:09.888
    • „Cleaning up orphan processes“: 17:22:10.911
    • Rechnerisch waren das rund 1,022 Sekunden; beobachtet blieb das Token nach dem Cleanup noch etwa 1 weitere Sekunde gültig, also insgesamt rund 2 Sekunden

PoC: Ausführung von artifact_racer.py

  • Zur Verifikation wurde das Python-Skript artifact_racer.py erstellt
  • Der Ablauf war wie folgt:
    • Es fragt fortlaufend ab, ob im Repository github/codeql-action der Workflow „PR Check – Debug artifacts after failure“ gestartet wurde
    • Es überwacht die Artefakte des laufenden Workflows
    • Sobald ein Artefakt erscheint, lädt es dieses herunter und extrahiert das GITHUB_TOKEN
    • Mit dem extrahierten Token erstellt es einen neuen Branch
    • In diesen Branch pusht es eine leere Datei namens poc.txt
    • Für den Commit erstellt es einen neuen Tag
  • Da das Artefakt etwa 21 MB groß war, wurde ein Erfolg innerhalb des Zeitfensters als realistisch eingeschätzt
  • Nach einem erfolgreichen Test in einem Test-Repository wurde das Skript gegen das Repository github/codeql-action ausgeführt
  • Rund zwei Stunden später lief der Workflow, und das Skript konnte das Token abrufen sowie Branch-Erstellung, File-Push und Tag-Erstellung erfolgreich durchführen

Wie Tag-Manipulation die Auswirkungen vergrößerte

  • Mit diesem Token konnten Angreifer bösartigen Code in ungeschützte Branches einbringen
  • Unauffälliger wäre auch eine Strategie gewesen, kleine bösartige Änderungen in einem Feature-Branch vor dem Merge unterzubringen und anschließend auf den Merge zu warten
  • Auch die Berechtigung zum Erstellen von Tags war kritisch
    • Wenn ein Commit mit bösartigem Code den Tag v3 erhalten hätte, hätten Nutzer, die codeql-action@v3 manuell einsetzen, den bösartigen Code ausführen können
  • Noch größer wurde die Wirkung durch die Standardkonfiguration von CodeQL
    • Wenn CodeQL in den Repository-Einstellungen als Standardkonfiguration aktiviert wird, läuft ein spezieller GitHub-Actions-Workflow, der in der Workflow-Liste des Repositories nicht sichtbar ist
    • Dieser Workflow führt Repository-Checkout, CodeQL-Initialisierung, CodeQL-Scan und Upload der Ergebnisse aus
    • Intern führt er die Action aus dem Repository github/codeql-action anhand des Commits aus, auf den der v3-Tag zeigt
  • Zu diesem Zeitpunkt war der v3-Tag nicht unveränderlich, und das von GitHub empfohlene Workflow-Pinning wurde nicht verwendet
  • Hätten Angreifer den kompromittierten GITHUB_TOKEN genutzt, um den v3-Tag auf einen bösartigen Commit zu verschieben, hätten Repositories mit dem Standard-CodeQL-Workflow die bösartige CodeQL-Action ausführen können
  • Da die CodeQL-Action den Quellcode des Ziel-Repositories auscheckt, hätte eine bösartige Action den Quellcode aus Repositories mit CodeQL-Standardkonfiguration exfiltrieren können

Angriffspfad über GitHub Actions Cache Poisoning

  • Das GITHUB_TOKEN der Standard-CodeQL-Action hat nur Leserechte, daher konnten mit der Standardkonfiguration allein keine Schreiboperationen am Repository, keine Release-Backdoor und kein unmittelbarer Secret-Diebstahl über workflow_dispatch durchgeführt werden
  • Allerdings läuft die Standard-CodeQL-Action auf dem main-Branch des Repositories
  • Der main-Branch eines GitHub-Repositories kann Cache-Einträge schreiben, die repositoryweit verwendet werden, wodurch sich eine Möglichkeit für GitHub Actions Cache Poisoning ergibt
  • GitHub Actions Cache Poisoning ist eine in Adnan Khans Beitrag beschriebene Technik; Cacheract ist Malware, die über Cache Poisoning Persistenz in Build-Pipelines herstellt
  • Wenn Angreifer Cacheract im CodeQL-Workflow ausbringen, wäre folgender Ablauf möglich gewesen:
    • Cache-Eintrag vorhersagen
    • Den betreffenden Eintrag mit einer bösartigen Action überschreiben
    • Codeausführung in Workflows erlangen, die actions/cache verwenden
    • GitHub-Actions-Secrets und höher privilegierte GITHUB_TOKENs aus diesen Workflows stehlen
  • Selbst wenn die bösartige CodeQL-Action entdeckt und die Schwachstelle behoben worden wäre, hätte Cacheract das Cache Poisoning weiter durchführen können
  • Als Beispiele für große Repositories, die sowohl CodeQL als auch actions/cache nutzen, wurden Homebrew, Angular und Grafana genannt

CVE-2025-24362 und die Behebung

  • Als Ergebnis dieser Offenlegung wurde CVE-2025-24362 vergeben
  • Das offengelegte GITHUB_TOKEN befand sich in einem Debug-Artefakt, das von der CodeQL-Action nach einem fehlgeschlagenen Code-Scanning-Workflow hochgeladen worden war
  • Das Repository der CodeQL Actions provozierte den Fehler absichtlich, doch auch bei anderen Nutzern der CodeQL Actions hätten ähnliche Fehler dazu führen können, dass ihre eigenen Secrets über Workflow-Umgebungsvariablen offengelegt werden
  • Das Problem wurde in CodeQL Action 3.28.3 behoben
  • Die größte potenzielle Auswirkung lag weniger in der CVE selbst als in dem Weg, die Schwachstelle gegen das Repository der CodeQL Actions auszunutzen und anschließend einen Lieferkettenangriff auf CodeQL-Nutzer durchzuführen

Reaktion von GitHub und empfohlene Gegenmaßnahmen

  • Die Reaktionszeitleiste von GitHub sah wie folgt aus:
      1. Januar 2025, 15:13 UTC: Meldung an GitHub eingereicht
      1. Januar 2025, 17:48 UTC: GitHub bestätigte den Eingang
      1. Januar 2025, 18:28 UTC: GitHub bestätigte die Schwachstelle, deaktivierte den Workflow „PR Check – Debug artifacts after failure“ vorläufig und reichte den PR zur Deaktivierung des Uploads von Debug-Artefakten ein
      1. Januar 2025: GitHub vergab CVE-2025-24362 und veröffentlichte das Security Advisory
  • Zur Verringerung des Risikos einer Secret-Offenlegung in GitHub-Actions-Workflow-Artefakten werden folgende Maßnahmen empfohlen:
    • Nur bestimmte Dateien oder Verzeichnisse als Workflow-Artefakte hochladen
    • Keine Artefakte hochladen, die Umgebungsvariablen, .git/config oder Dateien aus dem Runner-Verzeichnis <path_to_runner_dir>/_work/_temp/ enthalten
    • GITHUB_TOKEN-Berechtigungen auf read-only beschränken
    • Vor dem Artefakt-Upload einen Secret-Scan durchführen

1 Kommentare

 
GN⁺ 2025-04-01
Meinungen auf Hacker News
  • Wenn GitHub immutable actions früher energisch vorangetrieben hätte, wären die Auswirkungen solcher Vorfälle deutlich geringer gewesen.
    Ich sage immer wieder, dass diese Funktion derzeit über 70 % der Angriffsfläche von GitHub Actions abdecken würde. Wenn man sieht, dass jede Woche etwas passiert, ist es inzwischen wohl Zeit für den Rollout.
    [1] https://github.com/features/preview/immutable-actions

    • Wenn es noch im Preview-Status ist, hat das wahrscheinlich seinen Grund. Es könnte gravierende Bugs, Sicherheitslücken oder Kompatibilitätsbrüche geben, die bei überstürzter Einführung noch größeren Schaden anrichten würden.
  • Es gibt keine Erklärung dafür, warum dieses kurzlebige Token überhaupt die Berechtigung hatte, neue Deployments zu erstellen und Artifact Attestations zu erzeugen.
    Als Fix wurde gesagt, man habe Debug-Logs abgeschaltet, aber nicht beantwortet, ob die Berechtigungen des kurzlebigen Tokens passend für die Code-Analyse-Engine eingeschränkt wurden.

    • Klingt wie eine alte Geschichte, die jeder kennt. Der Engineer, der es gebaut hat, stieß auf eine Berechtigungsverweigerung, gab dann alle Rechte und kam später nie zurück, um es auf Least Privilege zu reduzieren.
    • Wenn ein kurzlebiges GitHub-Actions-Token keinen im Workflow definierten Berechtigungsumfang hat, gilt je nach Repository-Einstellung entweder ein permissiver oder ein restriktiver Standardumfang. Diese Einstellung kann auch auf Organisationsebene so konfiguriert werden, dass alle Repositories eingeschränkt werden.
      Früher gab es als Standard nur die permissive Einstellung, weshalb sie leider in vielen alten Organisationen und Repositories noch verwendet wird.
      Wenn man ein neues Repository erstellt, erbt es den Standard der übergeordneten Organisation; wenn niemand ihn ändert, bleibt dieser unsichere Standard also bestehen. Eine globale Benutzereinstellung gibt es nicht, daher nutzen neue persönliche Repositories einen restriktiven Standard. Neu erstellte Organisationen verwenden meines Wissens ebenfalls bessere Defaults.
      [0]: https://docs.github.com/en/actions/security-for-github-actio...
    • Kurzlebige Action-Tokens haben standardmäßig volle Schreibrechte. Für eine Read-only-Version muss man sich explizit entscheiden.

      Read and write permissions
      Workflows have read and write permissions in the repository for all scopes.
      Wenn man nur diese Zeile in der Dokumentation liest (https://docs.github.com/en/actions/security-for-github-actio...), kann man zu einem anderen Schluss kommen.
      If the default permissions for the GITHUB_TOKEN are restrictive, you may have to elevate the permissions to allow some actions and commands to run successfully.
      In unserer GitHub-Organisation war jedoch „Read and write permissions“ der Standard, daher kann ich bestätigen, dass dieser Satz in der Dokumentation keinen Sinn ergibt.

    • Der Microsoft-Hack von 2023 war ähnlich. CISA rügte öffentlich die schlechte Sicherheit, und selbst in dem Blogpost, den Microsoft zur Erklärung des Vorfalls veröffentlichte, blieben viel zu viele Fragen unbeantwortet.
    • Ich hoffe, das Abschalten der Debug-Logs war nur eine schnelle Zwischenmaßnahme. Es sollte nicht der endgültige Fix sein.
  • Ich bin immer stärker davon überzeugt, dass CI und CD vollständig getrennte Umgebungen sein sollten. Nur weil CI kompromittiert wird, dürfen keine CD-bezogenen Tokens durchsickern.

    • An diesem Bereich bin ich persönlich sehr interessiert; die Lösung sehe ich eher darin, CD wie einen Mehrfaktor-Mechanismus zu gestalten, statt CD als separates kleines Spezialsystem auszulagern.
      Zum Beispiel sollte eine Bedingung wie "sub":"repo:octo-org/octo-repo:environment:prod"[1] zwingend erfüllt sein; wenn man das System noch weiter härten will, kann man zusätzliche [fun claims][] ergänzen.
      1: https://docs.github.com/en/actions/security-for-github-actio...
      fun claims: https://github.com/github/actions-oidc-debugger#readme
    • Im Kern sieht so die Trennung von Aufgaben und Zuständigkeiten aus. Manche guten Projektbeispiele funktionieren genau so. Die konkreten Techniken, Tools und die Grenze zwischen CI und CD hängen von der Art des Endprodukts ab, aber konzeptionell ist das völlig richtig.
  • Die Reaktionszeit war kein Witz. GitHubs Reaktion ist ziemlich beeindruckend.

    • Dass ein öffentliches Token mit vollen Schreibrechten offengelegt wurde, ist weniger beeindruckend.
  • Als jemand mit dem Nachnamen Prater: Da dieser Name von Praetorian abgeleitet ist, hätte ich wirklich gern praetorian.com gehabt.

    • Dafür hättest du auf die Idee kommen müssen, bevor 1995 der Film „The Net“ herauskam.
    • Ihr gokart-Projekt war großartig.
  • Öffentliche GitHub Actions zu nutzen heißt, Ärger geradezu einzuladen – umso mehr, wenn man die Workflow-Prozeduren nicht analysiert.
    Besser wäre es, woodpecker oder andere gute CI-Builder (circle, travis, gitlab usw.) selbst zu hosten.

  • Wir haben CodeQL auf OpenZFS-PRs aktiviert. Für OpenZFS ist das kein Problem, denn unser Code ist nicht geheim. :)

    • Auch wenn der Code nicht geheim ist, halte ich das nicht für eine gute Entscheidung. Ein Angreifer hätte schließlich dem Code oder den Release-Artefakten alles Mögliche hinzufügen können.
      Immerhin wurde es zumindest schnell behoben.
  • Ist das behoben worden?

    • Wie im Artikel und in den Kommentaren hier steht: ja. Nachdem es im Januar gemeldet wurde, hat GitHub es innerhalb von 3 Stunden mitigiert.
  • Diese Website ist so schlecht performant, dass ich kaum scrollen kann.