flawopen.com/Teardowns/cve-2024-32002-git-submodule-rce
CVE-2024-32002: Git-Submodul-Symlink Remotecodeausführung (RCE)
CVE-2024-32002 ermöglichte einem präparierten Git-Repository, während eines rekursiven Klons über einen bei Groß-/Kleinschreibung kollidierenden Symlink in .git zu schreiben. Dadurch konnte ein Hook vor der Prüfung ausgeführt werden. Git prüft im Upstream-Fix das Submodulziel vor und nach dem Klonen und bricht bei unerwarteten Inhalten ab; aktualisieren Sie auf eine korrigierte Git-Version.
Stellen Sie sich ein Lager vor, dessen Schilder A und a als dieselbe Tür behandeln. Führt der Pfad eines Submoduls über ein Schild in den Aktenraum (.git), können Dateien für ein Lagerfach in Git-interne Steuerdaten gelangen. Der Git-Fix prüft das Ziel vor und nach dem Klonen und bricht bei unerwarteten Inhalten ab.
Kernkonzepte & Begriffe
Git-Submodul- Ein eigenständiges Git-Repository, das als Unterordner in ein Haupt-Repository eingebettet ist.
Symbolischer Link (Symlink)- Ein Dateisystemobjekt, das Pfade auf ein anderes Ziel verweist.
Case-Kollision- Verhalten von NTFS und APFS, bei dem Pfade unabhängig von Groß-/Kleinschreibung dasselbe Ziel referenzieren.
Git Hooks- Ausführbare Skripte in
.git/hooks/, die bei Vorgängen wiepost-checkoutautomatisch starten.
Framework-Zuordnungen
Ursachenanalyse
Auf einem groß-/kleinschreibungsunabhängigen Dateisystem mit Symlink-Unterstützung konnte ein präpariertes Repository einen Submodulpfad definieren, der nach der Groß-/Kleinschreibungsnormalisierung mit einem Symlink kollidierte. Beim rekursiven Klonen konnte Git ein für den Klon angelegtes Verzeichnis durch diesen Symlink ersetzen und Dateien außerhalb des Submodul-Worktrees in .git schreiben. Ein dort abgelegter Hook konnte laufen, bevor der Benutzer den Checkout prüfen konnte. Der Upstream-Patch verweigert das Klonen in ein bereits vorhandenes, nicht leeres Submodulziel und weist nach dem Klonen ein Ziel zurück, das mehr als .git-Metadaten enthält.
Schritt-für-Schritt Angriffsablauf
Der rekursive Klon erreicht repositorykontrollierte Metadaten
Eine Person klont ein nicht vertrauenswürdiges Repository rekursiv auf einem groß-/kleinschreibungsunabhängigen Dateisystem, auf dem Git Symlinks unterstützt. Das Repository enthält Submodulpfade und getrackte Einträge, die nach der Normalisierung kollidieren.
Die Pfadkollision überschreitet eine Vertrauensgrenze
Git kann den kollidierenden Submodulpfad über einen Symlink auflösen, statt ihn im vorgesehenen Submodul-Worktree anzulegen. Betroffen ist Git-Pfadauflösung während eines rekursiven Submodul-Klons.
Dateien gelangen in Git-Metadaten
Der umgeleitete Schreibvorgang kann einen Hook im .git-Bereich des Repositorys ablegen. Der Git-Projektbeitrag bestätigt, dass ein Hook dort geschrieben und noch während des Klonvorgangs ausgeführt werden kann.
Der Klon führt Code vor der Prüfung aus
Git führt den Hook während des Klons aus, bevor der Benutzer die ausgecheckten Dateien untersuchen kann. Korrigierte Git-Versionen prüfen den Zielzustand und brechen bei unerwarteten Dateien ab.
Quellcode: Verwundbar vs. Sicher
Dies ist ein Auszug aus der Upstream-C-Änderung in clone_submodule() und keine eigenständige Funktion. Vor dem Fix enthielt der gezeigte Klonpfad keine entsprechende Prüfung des Zielinhalts. Der Fix weist ein bereits vorhandenes, nicht leeres Checkout-Verzeichnis zurück und prüft nach dem Klonen, dass nur .git-Metadaten vorhanden sind; die Hilfsfunktion untersucht die Verzeichniseinträge. Der Upstream-Commit enthält die vollständige Implementierung.
if (!file_exists(sm_gitdir)) {
if (safe_create_leading_directories_const(sm_gitdir) < 0)
die(_("could not create directory '%s'"), sm_gitdir);
if (run_command(&cp))
die(_("clone of '%s' into submodule path '%s' failed"),
clone_data->url, clone_data_path);
}
struct stat st;
if (!file_exists(sm_gitdir)) {
if (clone_data->require_init && !stat(clone_data_path, &st) &&
!is_empty_dir(clone_data_path))
die(_("directory not empty: '%s'"), clone_data_path);
if (safe_create_leading_directories_const(sm_gitdir) < 0)
die(_("could not create directory '%s'"), sm_gitdir);
if (run_command(&cp))
die(_("clone of '%s' into submodule path '%s' failed"),
clone_data->url, clone_data_path);
if (clone_data->require_init && !stat(clone_data_path, &st) &&
!dir_contains_only_dotgit(clone_data_path)) {
char *dot_git = xstrfmt("%s/.git", clone_data_path);
unlink(dot_git);
free(dot_git);
die(_("directory not empty: '%s'"), clone_data_path);
}
}
Checkliste für Engineering & Systemsicherheit
- ✓Aktualisieren Sie Git auf 2.45.1, 2.44.1, 2.43.4 oder neuer, die Schutzmechanismen gegen Submodul-Kollisionen enthalten.
- ✓Deaktivieren Sie das automatische rekursive Submodul-Klonen in nicht vertrauenswürdigen Repositories (git clone --no-recurse-submodules).
- ✓Erzwingen Sie Prüfungen auf Dateipfad-Kollisionen in CI-Runnern und Build-Bots.
- ✓Setzen Sie core.protectNTFS und core.protectHFS in plattformübergreifenden Entwicklungsumgebungen auf true.
- ✓Prüfen Sie Repository-Checkouts auf verdächtige Symlinks, die auf interne .git-Verzeichnisse zeigen.