flawopen.com/Teardowns/cve-2024-32002-git-submodule-rce
CVE-2024-32002 : RCE via les Liens Symboliques des Sous-modules Git
CVE-2024-32002 permettait à un dépôt Git conçu à cet effet d’écrire dans .git via un lien symbolique dont le chemin entrait en collision par la casse lors d’un clone récursif, ce qui pouvait déclencher un hook avant toute inspection. Le correctif amont de Git vérifie la destination du sous-module avant et après le clone et interrompt l’opération si son contenu est inattendu ; mettez Git à niveau vers une version corrigée.
Imaginez un entrepôt où les panneaux considèrent A et a comme la même porte. Si le chemin d’un sous-module passe par un panneau qui redirige vers la salle des registres (.git), des fichiers destinés à une zone peuvent se retrouver dans les données de contrôle de Git. Le correctif vérifie la destination avant et après le clone et s’arrête si son contenu est inattendu.
Concepts Clés et Termes
Sous-module Git- Un dépôt Git distinct intégré comme sous-dossier dans un dépôt parent.
Lien Symbolique- Un objet de système de fichiers redirigeant les chemins vers une autre cible.
Collision de Casse- Comportement sur NTFS et APFS où deux chemins ne différant que par la casse désignent le même fichier.
Crochets Git (Git Hooks)- Scripts exécutables dans
.git/hooks/déclenchés automatiquement parpost-checkout.
Correspondances de référentiels
Analyse de Cause Racine
Sur un système de fichiers insensible à la casse qui prend en charge les liens symboliques, un dépôt conçu à cet effet pouvait donner à un sous-module un chemin entrant en collision, après normalisation de la casse, avec un lien symbolique. Pendant un clone récursif, Git pouvait remplacer par ce lien un répertoire créé pour le clone et écrire des fichiers hors du worktree du sous-module, dans .git. Un hook placé à cet endroit pouvait s’exécuter avant que l’utilisateur n’inspecte le checkout. Le correctif amont refuse de cloner vers une destination de sous-module préexistante et non vide puis, après le clone, rejette toute destination dont le contenu dépasse les métadonnées .git.
Déroulement de l'Attaque Étape par Étape
Le clone récursif atteint des métadonnées contrôlées par le dépôt
Une personne clone récursivement un dépôt non fiable sur un système de fichiers insensible à la casse où Git prend en charge les liens symboliques. Le dépôt fournit des chemins de sous-modules et des entrées suivies qui entrent en collision après normalisation de la casse.
La collision de chemins franchit une frontière de confiance
Git peut résoudre le chemin du sous-module en collision à travers un lien symbolique, au lieu de le placer dans le worktree prévu. La frontière concernée est la résolution des chemins du système de fichiers pendant le clone récursif des sous-modules.
Des fichiers atteignent les métadonnées Git
L’écriture redirigée peut placer un hook dans la zone .git du dépôt. L’avis du projet Git confirme qu’un hook peut y être écrit puis exécuté pendant que le clone est encore en cours.
Le clone peut exécuter du code avant inspection
Git exécute le hook pendant l’opération de clone, avant que l’utilisateur puisse examiner les fichiers. Les versions corrigées vérifient l’état de la destination et interrompent le clone si des fichiers inattendus sont présents.
Code Source : Vulnérable vs Sécurisé
Cet extrait montre une partie du changement amont en C dans clone_submodule() ; il ne constitue pas une fonction autonome. Avant le correctif, le chemin de clone affiché ne comportait pas de contrôle équivalent du contenu de destination. Le correctif refuse un répertoire de checkout préexistant non vide puis vérifie après le clone que seuls les métadonnées .git sont présents ; la fonction auxiliaire inspecte les entrées du répertoire. Le commit amont fournit l’implémentation complète.
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);
}
}
Liste de Contrôle de Sécurité pour l'Ingénierie
- ✓Mettez Git à jour en 2.45.1, 2.44.1, 2.43.4 ou ultérieur, qui contiennent des protections contre les collisions de sous-modules.
- ✓Désactivez le clone récursif automatique des sous-modules pour les dépôts non fiables (git clone --no-recurse-submodules).
- ✓Imposez des vérifications de collision de chemins de fichiers dans les runners d'intégration continue et les bots de build.
- ✓Réglez core.protectNTFS et core.protectHFS sur true dans les environnements de développement multiplateformes.
- ✓Auditez les checkouts de dépôt à la recherche de liens symboliques suspects ciblant des répertoires .git internes.