1 points par GN⁺ 2 시간 전 | 1 commentaires | Partager sur WhatsApp
  • gokrazy/rsync est une implémentation minimale de rsync écrite en Go, examinée à l’aune de 12 vulnérabilités rsync publiées en janvier 2025 et mai 2026
  • Les vérifications de limites de Go et son initialisation à zéro transforment les débordements de tas et les fuites d’informations de pile en panic ou en valeurs inoffensives, mais une panic peut malgré tout provoquer un déni de service
  • Pour les vulnérabilités de type traversée de chemin et TOCTOU, des API de fichiers résistantes à la traversée comme os.Root de Go 1.24 constituent une défense clé, et gokrazy/rsync a été entièrement migré vers elles
  • La stratégie d’implémentation minimale permet d’éviter des vulnérabilités liées à des fonctionnalités non implémentées comme --inc-recursive, la compression, --safe-links, les proxys ou les ACL de noms d’hôte, ce qui réduit la surface d’attaque
  • La plupart des vulnérabilités provenaient d’une validation insuffisante et d’une complexité excessive, et pour des cas d’usage simples, une implémentation simple peut être plus appropriée

Contexte et périmètre

  • En janvier 2025, plusieurs chercheurs en sécurité ont publié un total de 6 vulnérabilités dans l’upstream Samba rsync, dont certaines permettaient l’exécution de code arbitraire et l’exfiltration de fichiers
  • La question centrale de l’examen est de savoir si gokrazy/rsync, implémentation compatible et minimale écrite en Go, peut réellement éviter ces familles de vulnérabilités
  • L’analyse couvre 12 vulnérabilités au total, en combinant la vague de janvier 2025 et celle de mai 2026
  • Si vous exécutez l’upstream rsync en production, vous devez passer à la version 3.4.3 ou ultérieure ; pour gokrazy/rsync, il faut passer à la v0.3.3 ou ultérieure
  • gokrazy/rsync a été écrit pour fournir sur router7 les paquets logiciels du projet de recherche sur les distributions Linux distri, router7 reposant sur la plateforme d’appliances Go gokrazy
  • Au départ, seul le serveur rsync existait, mais il prend désormais en charge toutes les directions et sert de fonctionnalité rsync de base pouvant être liée à des programmes Go, utilisée dans plusieurs serveurs gokrazy/rsync

Vulnérabilités de janvier 2025

  • CVE-2024-12084 : dépassement de tampon sur le tas, sévérité 9,8

    • rsync comparait la longueur de la somme de contrôle reçue sur le réseau à MAX_DIGEST_LEN, mais sa structure de données interne utilisait toujours un tampon fixe de 16 octets, char sum2[SUM_LENGTH]
    • MAX_DIGEST_LEN peut être plus grand quand la prise en charge des sommes de contrôle SHA256 ou SHA512 est compilée, ce qui permettait à un attaquant d’écrire jusqu’à 48 octets au-delà des limites du tampon sum2
    • Le problème a été introduit en septembre 2022 dans le commit ae16850, qui a ajouté la prise en charge des sommes de contrôle SHA256/SHA512
    • Le correctif upstream remplace sum2 par sum2_array, alloué dynamiquement, et corrige l’allocation et les vérifications pour qu’elles utilisent xfer_sum_len, la longueur de somme de contrôle de l’algorithme de transfert
    • En Go, une vérification de bornes incorrecte ne conduit pas à un dépassement de tampon sur le tas, mais à un panic déclenché par la vérification des bornes à l’exécution
    • gokrazy/rsync avait aussi une vérification manquante de l’en-tête de somme, mais il ne s’agissait pas d’une confusion de taille ; si ChecksumLength est changé en 512, le runtime Go déclenche panic: runtime error: slice bounds out of range [:512] with length 16
    • Un crash complet du serveur n’est pas un mode d’échec souhaitable, donc une vérification de bornes manquante a été ajoutée pour transformer le panic en error
  • CVE-2024-12085 : fuite d’informations de la pile permettant de contourner l’ASLR, sévérité 7,5

    • À cause de la même validation manquante que pour CVE-2024-12084, un attaquant pouvait choisir un algorithme de somme de contrôle court puis prétendre avoir envoyé une somme plus longue
    • Selon le Google Security report, la combinaison du dépassement de tampon sur le tas et de la fuite d’informations permet à un client ne disposant que d’un accès en lecture anonyme d’exécuter du code arbitraire sur la machine serveur rsync
    • hash_search() construisait le digest du bloc dans char sum2[MAX_DIGEST_LEN] sur la pile et le comparait avec memcmp(), mais le tampon local sum2 sur la pile n’était pas initialisé, si bien que les octets restants pouvaient contenir du contenu de la pile
    • Un client malveillant pouvait exfiltrer 1 octet par téléchargement de fichier, et les données divulguées pouvaient inclure des pointeurs vers des objets du tas, le stack cookie, des variables locales, des pointeurs vers des variables globales et le pointeur de retour
    • “Some checksum buffer fixes” a empêché la valeur contrôlée par l’attaquant s->s2length de dépasser la longueur de somme de contrôle de transfert, et “prevent information leak off the stack” a initialisé la mémoire de sum2 à 0
    • Go initialise toutes les variables à leur zero value, donc cette vulnérabilité ne l’affecte pas, et gokrazy/rsync implémente la version 27 du protocole, pas la version 30 qui a introduit la sélection de sommes de contrôle autres que MD4
  • CVE-2024-12087 : traversée de chemin via lien symbolique, sévérité 7,5

    • Selon le Google Security report, quand la synchronisation des liens symboliques est activée avec -l ou -a (--archive), un serveur malveillant peut amener le client à écrire des fichiers arbitraires en dehors du répertoire cible
    • L’attaque consiste à envoyer plusieurs listes de fichiers en mode --inc-recursive ; dans la première liste, symlink est présenté comme un répertoire, puis dans une liste suivante, le même nom est remplacé par un lien symbolique pointant hors du répertoire cible
    • Go en lui-même ne peut pas empêcher cette vulnérabilité, car la cause est une erreur logique : plusieurs listes de fichiers sont fusionnées puis non revalidées
    • Le correctif upstream ajoute la validation manquante
    • gokrazy/rsync n’est pas affecté, car il n’implémente pas le mode de récursion incrémentale (--inc-recursive)
    • La récursion incrémentale permet de traiter l’ensemble des fichiers de manière « windowed » sans tout analyser avant le début du transfert, mais cela implique un compromis entre complexité d’implémentation et consommation de ressources
  • CVE-2024-12088 : contournement de --safe-links, sévérité 7,5

    • Selon le Google Security report, --safe-links est une fonctionnalité qui vérifie que les liens symboliques reçus du serveur pointent à l’intérieur du répertoire cible
    • Le contournement est dû au fait qu’il ne tenait pas compte de la présence d’un autre lien symbolique au milieu du chemin cible du lien symbolique
    • Par exemple, si {DESTINATION}/a -> . et {DESTINATION}/foo -> a/a/a/a/a/a/../../ existent, alors foo pointe en réalité hors du répertoire cible, mais unsafe_symlink() le juge sûr en supposant que a/ est un répertoire
    • Le correctif upstream rend unsafe_symlink() plus strict en n’autorisant plus ../ sauf au début du chemin
    • Go en lui-même ne peut pas empêcher une fonction de validation incorrecte, et gokrazy/rsync n’est pas vulnérable car il n’implémente pas encore la fonctionnalité --safe-links
  • CVE-2024-12086 : exfiltration de fichiers arbitraires, sévérité 6,8

    • Le receiver rsync, en mode client, ne nettoyait pas les noms de fichiers fournis par le sender rsync et n’empêchait pas l’ouverture de fichiers en dehors de l’arborescence cible
    • Un sender malveillant pouvait demander au receiver de comparer la somme de contrôle de fichiers arbitraires hors de l’arborescence cible, puis observer la réaction du receiver à une somme de contrôle d’un octet pour exfiltrer ces fichiers
    • Selon le Google Security report, lorsqu’un client se connecte à un serveur malveillant, celui-ci peut exfiltrer le contenu de fichiers arbitraires de la machine cliente
    • Le correctif upstream valide les chemins fournis par le sender afin d’empêcher l’ouverture de fichiers en dehors de l’arborescence cible
    • Go fournit des API permettant d’empêcher cela, et os.Root de Go est cité comme défense pertinente
    • gokrazy/rsync n’est pas vulnérable, car il implémente la version 27 du protocole, pas la version 29 qui a introduit la fonctionnalité de fuzzy matching
  • CVE-2024-12747 : condition de concurrence sur lien symbolique, sévérité 5,6

    • Selon le Red Hat Security Advisory, il s’agit d’un défaut lié à une condition de concurrence dans la gestion des liens symboliques par rsync
    • Le comportement par défaut de rsync est d’ignorer les liens symboliques, mais un attaquant pouvait contourner ce comportement par défaut et faire suivre un lien symbolique en remplaçant un fichier ordinaire par un lien symbolique au bon moment
  • Le correctif upstream modifie l’appel à open() du sender rsync pour utiliser l’option O_NOFOLLOW

    • gokrazy/rsync était vulnérable jusqu’au commit 1b1fbf6, qui introduit la même mitigation O_NOFOLLOW que rsync upstream
    • Damien Neil a estimé que le correctif CVE-2024-12747 de gokrazy était insuffisant, jugeant que O_NOFOLLOW empêche seulement le suivi des liens symboliques sur le dernier composant du chemin
    • Par exemple, avec os.Open("dir/passwd"), il reste possible de contourner la protection si un composant précédent du chemin, dir, est remplacé par un lien symbolique pointant vers /etc
    • Le problème a été signalé au contact sécurité de rsync en avril 2025, ce qui a conduit au CVE-2026-29518, rendu public le 2026-05-20

Vulnérabilités de mai 2026

  • CVE-2026-29518 : condition de course sur lien symbolique, gravité 7.0

    • Selon la NEWS entry de rsync 3.4.3, il s’agit d’une condition de course TOCTOU sur lien symbolique permettant une élévation locale de privilèges en mode daemon sans chroot
    • Un daemon rsync configuré avec use chroot = no est exposé à une course time-of-check/time-of-use sur un composant parent du chemin
    • Un attaquant local disposant d’un accès en écriture au module peut remplacer un composant du répertoire parent par un lien symbolique entre la vérification du receiver et open(), provoquant une divulgation du basis-file en lecture et un écrasement de fichier hors du module en écriture
    • La valeur par défaut use chroot = yes n’est pas exposée
    • Le correctif upstream utilise secure_relative_open(), similaire à l’API os.Root de Go
    • gokrazy/rsync a été vulnérable jusqu’à ce que le sender et le receiver passent à l’API os.Root résistante à la traversée
  • CVE-2026-43618 : fuite mémoire distante via débordement entier, gravité 8.1

    • Le décodeur de jetons de compression du receiver rsync accumule un compteur signé 32 bits sans vérification de débordement, ce qui permet à un sender malveillant d’exfiltrer le contenu de la mémoire du processus
    • Les données exfiltrées peuvent inclure des variables d’environnement, des mots de passe, des pointeurs du tas et de bibliothèques, ce qui affaiblit l’ASLR et facilite d’autres exploits
    • Le périmètre d’impact couvre les connexions daemon authentifiées avec compression activée, celle-ci étant activée par défaut à partir du protocole 30 si les deux pairs annoncent la compression
    • La mesure de contournement consiste à désactiver la compression du daemon dans rsyncd.conf avec refuse options = compress
    • Le correctif upstream ajoute les vérifications manquantes
    • gokrazy/rsync n’est pas vulnérable car il n’implémente pas la compression, et les raisons non triviales pour lesquelles la prise en charge de la compression paraît simple sont résumées dans gokrazy/rsync issue #35
  • CVE-2026-43620 : déni de service après lecture hors limites, gravité 6.5

    • Le garde-fou parent_ndx<0 ajouté à send_files() en 2025 n’a pas été appliqué au bloc visuellement identique de recv_files(), d’où le problème
    • Si un serveur rsync malveillant envoie un drapeau de compatibilité CF_INC_RECURSE et une flist mal formée, le receiver peut lire puis déréférencer dir_flist->files[-1], entraînant un SIGSEGV déterministe
    • Le périmètre d’impact couvre tous les clients rsync effectuant un pull classique depuis une URL contrôlée par un attaquant, sans option spéciale côté victime à cause de inc_recurse, valeur par défaut à partir du protocole 30
    • Utiliser --no-inc-recursive côté client est une mesure de contournement, et le correctif upstream ajoute aussi le garde-fou parent_ndx<0 à recv_files()
    • gokrazy/rsync n’est pas affecté, comme pour CVE-2024-12087, car il n’implémente pas le mode de récursion incrémentale --inc-recursive
  • CVE-2026-43619 : condition de course supplémentaire sur lien symbolique, gravité 6.3

    • Le correctif de la condition de course sur lien symbolique pour les appels open() du receiver (CVE-2026-29518) n’a pas été appliqué à d’autres appels système basés sur des chemins comme chmod, lchown, utimes, rename, unlink, mkdir, symlink, mknod, link, rmdir, lstat, etc.
    • Dans un daemon rsync configuré avec use chroot = no, un attaquant local peut remplacer un composant du répertoire parent par un lien symbolique entre la vérification du receiver et l’appel système, afin de rediriger l’opération hors du module exporté
    • La valeur par défaut use chroot = yes n’est pas exposée
    • Le correctif upstream traite les appels système concernés via un dirfd parent ouvert sous des restrictions imposées par le noyau, comme openat2 sur Linux 5.6+, O_RESOLVE_BENEATH sur FreeBSD 13+ et macOS 15+, ou une traversée composant par composant avec O_NOFOLLOW ailleurs
    • gokrazy/rsync n’est pas affecté parce qu’il utilise l’API os.Root de Go de manière généralisée
  • CVE-2026-43617 : contournement d’ACL basé sur le nom d’hôte, gravité 4.8

    • Sur un daemon rsync avec le réglage rsyncd.conf global daemon chroot = /X, la résolution DNS inverse du client se connectant était effectuée après que le daemon avait fait un chroot vers /X
    • Si /X ne contient pas /etc/resolv.conf, /etc/nsswitch.conf, /etc/hosts ni les modules de service NSS requis pour la résolution glibc, la recherche échoue et le nom d’hôte de connexion est défini sur "UNKNOWN"
    • Les règles de refus basées sur le nom d’hôte comme hosts deny = *.evil.example ne correspondent alors pas, permettant à un attaquant contrôlant les enregistrements PTR de se connecter depuis un nom d’hôte que l’administrateur voulait bloquer
    • Les ACL basées sur IP ne sont pas affectées, et le réglage use chroot par module n’a aucun lien avec cette vulnérabilité
    • Le correctif upstream déplace la résolution DNS plus tôt dans le protocole
    • gokrazy/rsync n’est pas vulnérable car il n’implémente pas de listes allow/deny basées sur le nom d’hôte, mais uniquement des listes allow/deny basées sur IP
  • CVE-2026-45232 : écriture hors limites sur la pile, gravité 3.1

    • La prise en charge du proxy HTTP CONNECT dans le client rsync comporte une écriture hors limites sur la pile de type off-by-one dans establish_proxy_connection()
    • Si un proxy ou un attaquant man-in-the-middle renvoie plus de 1023 octets sans '\n' dans la première ligne de réponse, le code suivant peut écrire '\0' juste après le tampon de 1024 octets, corrompant un slot adjacent de la pile
    • AddressSanitizer signale un stack-buffer-overflow à socket.c:95 dans la frame establish_proxy_connection
    • Le correctif upstream valide les données fournies par l’attaquant
    • gokrazy/rsync n’est pas vulnérable car il n’implémente pas cette prise en charge du proxy

Ce que Go et gokrazy/rsync ont réellement empêché

  • Les vérifications de limites du runtime Go transforment des problèmes de sécurité plus graves en panic ; un panic reste un risque de déni de service, mais il est considéré comme un meilleur mode d’échec
  • Go initialise la mémoire à zéro, ce qui rend impossibles les fuites d’informations comme CVE-2024-12085
  • L’API os.Root de Go empêche la plupart des vulnérabilités restantes
  • Sur 12 vulnérabilités, une seule, CVE-2026-43617, est classée comme un bug de logique applicative qui ne peut pas être évité simplement en utilisant Go
  • La différence essentielle entre gokrazy/rsync et rsync upstream officiel, au-delà du fait qu’il est écrit en Go, est que l’implémentation est minimale
  • gokrazy/rsync n’implémente pas plusieurs fonctionnalités en cause, comme --inc-recursive, --safe-links, la compression, les proxys ou les ACL par nom d’hôte, ce qui lui permet d’éviter plusieurs vulnérabilités
  • Comme toute implémentation rsync compatible avec le wire protocol, gokrazy/rsync cible la version 27 du protocole, les versions ultérieures introduisant une complexité importante
  • État de gokrazy/rsync pour chaque CVE au moment de la publication :
    • 2024-12084 : l’implémentation existait et provoquait un panic
    • 2024-12085 : fonctionnalité du protocole 30, donc non implémentée et non vulnérable
    • 2024-12086 : fonctionnalité du protocole 29, donc non implémentée et non vulnérable
    • 2024-12087 : non vulnérable car inc-rec n’est pas implémenté
    • 2024-12088 : non vulnérable car safe-links n’est pas implémenté
    • 2024-12747 : l’implémentation existait et était vulnérable
    • 2026-29518 : l’implémentation existait et a été corrigée
    • 2026-43617 : non vulnérable car la liste deny d’hôtes n’est pas implémentée
    • 2026-43618 : non vulnérable car la compression n’est pas implémentée
    • 2026-43619 : l’implémentation existait et a été corrigée
    • 2026-43620 : non vulnérable car inc-rec n’est pas implémenté
    • 2026-45232 : non vulnérable car les proxys ne sont pas implémentés
  • Toutes les vulnérabilités connues de gokrazy/rsync ont été corrigées, et l’état ci-dessus reflète la situation au moment où chaque CVE a été rendue publique
  • Lors de la divulgation des vulnérabilités en janvier 2025, gokrazy/rsync provoquait un panic sur CVE-2024-12084 et était vulnérable à la condition de concurrence TOCTOU de CVE-2024-12747
  • Lors de la correction du problème TOCTOU, CVE-2026-29518 a été découverte et corrigée dans gokrazy/rsync avant la publication de ce CVE
  • CVE-2026-43619 a été découverte plus tard, mais était déjà résolue dans gokrazy/rsync par la même correction, à savoir l’utilisation généralisée de os.Root

Distinction des rôles et dénomination des vulnérabilités

  • Plusieurs rapports de vulnérabilité utilisaient les termes « server » et « client », mais dans un transfert rsync, le client rsync comme le serveur peuvent tous deux jouer le rôle d’émetteur (sender, upload de fichiers) ou de récepteur (receiver, téléchargement de fichiers)
  • En mode démon, il est possible de limiter l’accès au système de fichiers à des chemins de modules préconfigurés, mais pas en command mode
  • Les 4 configurations ainsi que les couches rôle/protocole sont visibles dans le diagramme rsync combinations
  • Le titre d’origine de la vulnérabilité Arbitrary File Leak (CVE-2024-12086), « Server leaks arbitrary client files », prête facilement à confusion
  • Une formulation plus précise est que le récepteur rsync divulgue des fichiers arbitraires à un émetteur malveillant
  • Un client émetteur malveillant peut, dans un environnement comme le command mode via SSH, amener un rsync distant non corrigé à ouvrir des fichiers hors de l’arborescence cible, par exemple la base système de mots de passe /etc/shadow
  • En mode démon, le serveur active une normalisation de chemin supplémentaire (path sanitization) pour bloquer cette attaque
  • La vulnérabilité Symlink Path Traversal (CVE-2024-12087) est elle aussi décrite comme impliquant un « malicious server », alors qu’il s’agit plus précisément d’un émetteur malveillant, qu’il s’agisse du client ou du serveur

Comparaison avec openrsync d’OpenBSD

  • Le projet OpenBSD est connu pour son attention à la sécurité, et openrsync valide la longueur des checksums et ne prend en charge que MD4 pour la taille/l’algorithme de checksum, ce qui le rend non affecté par Heap Buffer Overflow (CVE-2024-12084) et Stack Info Leak (CVE-2024-12085)
  • Comme gokrazy/rsync, openrsync n’implémente pas les fonctionnalités concernées et n’est donc pas affecté par CVE-2024-12086, CVE-2024-12087 et CVE-2024-12088
  • Même s’il avait été vulnérable, lorsqu’il s’exécute sur OpenBSD, OpenBSD unveil(2) et pledge(2) auraient pu empêcher une exploitation réussie grâce à une défense en profondeur limitant l’accès au système de fichiers
  • openrsync utilise O_NOFOLLOW depuis l’instant où il a implémenté la prise en charge des liens symboliques, ce qui le rend non affecté par CVE-2024-12747
  • Mais O_NOFOLLOW n’est pas une correction suffisante pour ce problème ; openrsync est donc affecté par CVE-2026-29518
  • Le lot de mai 2026 est similaire en ce que, là aussi, la plupart des fonctionnalités concernées ne sont pas implémentées
  • openrsync n’est pas affecté par la majorité des vulnérabilités signalées grâce à une validation sérieuse, une surface d’attaque limitée et l’application d’une défense en profondeur

Défense en profondeur et os.Root

  • Espace de noms de montage Linux

    • Quelques semaines après le lancement du projet gokrazy/rsync, une fonctionnalité a été ajoutée pour prendre en charge l’abaissement de privilèges ainsi que l’utilisation des espaces de noms mount/pid sous Linux afin de limiter l’accès aux objets du système de fichiers
    • Cette approche fonctionne bien pour atténuer les attaques de traversée de chemin, mais elle nécessite des privilèges, ce qui impose de l’exécuter en tant que root ou à l’intérieur d’un espace de noms utilisateur Linux si celui-ci est activé par la distribution ou le système
    • L’espace de noms de montage convient bien à une configuration serveur, mais il est souvent inutilisable pour des transferts interactifs ponctuels lancés depuis le compte d’un utilisateur ordinaire
  • Renforcement avec systemd

    • Le même commit qui a introduit la prise en charge des espaces de noms mount/pid sous Linux incluait aussi un fichier de service systemd limitant l’accès au système de fichiers au répertoire personnel, et le README recommande de restreindre encore davantage cet accès selon le cas d’usage
    • Lorsque ces restrictions du système de fichiers sont correctement configurées, elles atténuent les vulnérabilités File Leak (CVE-2024-12086) et Path Traversal (CVE-2024-12087)
    • Symlink Race Condition (CVE-2024-12747) repose sur une élévation de privilèges via le processus rsync, mais grâce à la fonctionnalité DynamicUser, le processus dispose de moins de privilèges que les autres utilisateurs
    • Comme l’espace de noms de montage, c’est très bien pour une configuration serveur, mais fastidieux à mettre en place pour un usage interactif ponctuel
  • Linux Landlock

    • Porting OpenBSD pledge() to Linux (2022) a rappelé qu’il existe aussi sous Linux une API Landlock, un contrôle d’accès non privilégié et par processus comparable à unveil(2) d’OpenBSD
    • L’idée de base est que, une fois que le programme connaît le répertoire sur lequel il va travailler, un appel comme unveil("/home/michael/backups", "rw"); peut l’empêcher d’accéder à tout autre emplacement du système de fichiers
    • En mars 2025, la prise en charge de Landlock a été implémentée pour restreindre l’accès au système de fichiers
    • Une fois la configuration en place, même une exécution non privilégiée de gokrazy/rsync peut limiter un transfert rsync à un accès en lecture seule sur la source et en lecture-écriture sur le répertoire de destination
    • Son inconvénient est que Landlock fonctionne au niveau du processus
    • La politique Landlock doit aussi inclure les fichiers nécessaires au programme ; par exemple, gokrazy/rsync doit pouvoir lire /etc/passwd pour résoudre les identifiants utilisateurs, donc si un attaquant vise /etc/passwd, Landlock n’aide pas
  • os.Root de Go

    • En février 2025, Go 1.24 a introduit l’API os.Root, résistante à la traversée de chemin, et le contexte associé est résumé dans The Go Blog: Traversal-resistant file APIs de Damien Neil
    • Par rapport à Landlock, os.Root offre un contrôle plus fin, opération par opération, sur les interactions avec le système de fichiers
    • Lancé en août 2025, Go 1.25 a ajouté davantage de méthodes à os.Root, ce qui en fait une option pratique pour la plupart des usages du système de fichiers
    • Tous les usages du système de fichiers dans gokrazy/rsync ont été migrés vers os.Root, ce qui correspond bien au modèle où l’utilisateur configure les répertoires d’entrée et de sortie, mais où les noms de fichiers reçus via le réseau ne sont pas dignes de confiance
    • Même des appels système comme mknod(2), qui semblent impossibles à créer directement via l’API, peuvent être utilisés de manière sûre
    • Damien Neil explique qu’on peut ouvrir le répertoire parent de la cible avec os.Root.OpenFile, récupérer le descripteur de fichier de ce répertoire via File.Fd, puis créer le fichier avec golang.org/x/sys/unix#Mknodat
    • Un exemple concret figure dans internal/receiver/generatormknod_linux.go, ligne 15-29
    • Linux dispose bien de mknodat(2), mais pas, au moins jusqu’à Linux 7.0, d’un bindat correspondant à bind(2)
    • Lennart Poettering a proposé qu’en l’absence de bindat, on puisse binder sur /proc/self/<fd>/foobar en utilisant une astuce qui évite la résolution de chemin
    • Si, après un /proc/self/<fd> connu comme sûr, on ne fournit pas un chemin mais seulement un basename, c’est-à-dire le dernier composant du chemin, la résolution de chemin est contournée ; le code correspondant se trouve lignes 49-56
    • Grâce à ces deux astuces, gokrazy/rsync v0.3.1 et versions ultérieures utilisent entièrement os.Root, et tous les accès au système de fichiers bénéficient d’une sécurité contre la traversée de chemin

Enseignements clés

  • Toutes les vulnérabilités, à l’exception des failles TOCTOU (CVE-2024-12747, CVE-2026-29518, CVE-2026-43619), proviennent d’une absence de validation des entrées ou d’une validation incorrecte des entrées
  • Dans trois cas, il n’y avait tout simplement aucune validation au départ, et CVE-2024-12088 relève d’un sujet difficile, la résolution des chemins du système de fichiers, où la validation existante ne couvrait pas tous les cas limites
  • La correction structurelle la plus utile consiste à fournir une validation toujours active, comme les vérifications de bornes, ainsi que des API sûres par défaut comme os.Root de Go
  • Certaines vulnérabilités sont apparues avec l’évolution du protocole rsync, lorsque de nouvelles fonctionnalités ont été ajoutées à un code qui validait correctement à l’origine, sans que cette validation soit mise à jour comme il fallait
  • La négociation de l’algorithme de somme de contrôle et la récursion incrémentale ont été ajoutées dans la version 30 du protocole, et la validation existante n’a pas été actualisée pour correspondre à la façon dont ces nouvelles fonctionnalités étaient traitées
  • gokrazy/rsync et openrsync n’étaient pas vulnérables à 8 des 12 failles de sécurité simplement parce qu’ils n’implémentaient pas les fonctionnalités vulnérables
  • Ces fonctionnalités ont été ajoutées à rsync parce qu’elles avaient de la valeur pour quelqu’un à un moment donné, ce qui ne signifie pas qu’il faille arrêter de développer des logiciels
  • Le choix idéal consiste à utiliser une implémentation dont la complexité est adaptée et proportionnée à celle du cas d’usage : choisir une implémentation simple pour des usages simples, et ne recourir à une implémentation complète que lorsque c’est nécessaire

1 commentaires

 
GN⁺ 2 시간 전
Commentaires sur Lobste.rs
  • Excellent article. C’est suffisamment bien pour que tous les langages aient des API comme os.Root dans leur bibliothèque standard
    Après avoir rencontré plusieurs vulnérabilités de traversée de chemin sur SecureDrop, nous avons utilisé une version très simplifiée, et maintenant, avec la bonne API, toute une catégorie de vulnérabilités disparaît d’un coup
    • Oui. Le véritable protagoniste de ce billet de blog semble être moins Go que os.Root