1 points par GN⁺ 2024-07-31 | 1 commentaires | Partager sur WhatsApp
  • L’audit de Trail of Bits a identifié dans Homebrew, le gestionnaire de paquets de facto de l’écosystème des développeurs macOS, des possibilités d’exécution de code inattendue et d’affaiblissement de l’intégrité des builds ; les constats n’étaient toutefois pas d’un niveau critique
  • Le périmètre couvrait Homebrew/brew, qui contient le CLI brew, ainsi que Homebrew/actions, Homebrew/formulae.brew.sh et Homebrew/homebrew-test-bot, en examinant à la fois le gestionnaire de paquets local et les frontières CI/CD
  • Les problèmes côté brew pouvaient mener à une injection de chaînes dans la configuration du sandbox, à des collisions d’espaces de noms fondées sur MD5, à l’inclusion de ressources réseau non déclarées, à un pivot via socket sur macOS, à l’abus de jetons sudo et à la possibilité d’installer des formulae depuis des URL non locales
  • Côté CI/CD, le déclencheur pull_request_target et des entrées workflow_dispatch non validées pouvaient ouvrir des voies vers la falsification de builds de bottles, l’exposition d’identifiants, l’élévation de privilèges et l’obtention de persistance sur des runners GitHub Actions auto-hébergés
  • Homebrew repose sur l’hypothèse de formulae fiables, mais comme une formula est elle-même du code Ruby exécutable et que la surface API/CLI est large, il est difficile de maintenir de façon cohérente les frontières d’isolation et d’intégrité

Périmètre et cibles de l’audit

  • Trail of Bits a réalisé l’été dernier un audit de Homebrew
  • Les cibles de l’audit étaient Homebrew/brew, qui contient le CLI brew, ainsi que trois dépôts adjacents importants pour la sécurité
  • L’Open Tech Fund a financé l’audit dans le cadre de ses activités visant à renforcer la sécurité des composants essentiels de l’infrastructure Internet
  • Le rapport complet est disponible dans le dépôt publications de Trail of Bits

Pourquoi Homebrew est important

  • Homebrew se présente comme « le gestionnaire de paquets manquant pour macOS ou Linux » et joue le rôle de gestionnaire de paquets de facto pour les développeurs macOS
  • Il traite chaque année des centaines de millions d’installations de paquets, y compris des paquets essentiels comme Golang, Node.js et OpenSSL
  • L’intégrité des builds de ces paquets est liée à la sécurité de l’écosystème logiciel en aval, au-delà de Homebrew lui-même
  • Le cœur de Homebrew est un monolithe Ruby qui fournit le CLI brew et une API Ruby réutilisable
  • Depuis son lancement en 2009, Homebrew a modifié plusieurs fois son architecture afin d’améliorer la fiabilité et l’utilisabilité des paquets
    • Introduction des bottles, des builds binaires
    • Adoption des bottles comme mode d’installation par défaut, en remplacement des builds locaux depuis les sources
    • Construction des bottles uniquement en CI/CD afin de réduire l’impact de machines de développement compromises
  • Le mode d’installation est devenu de plus en plus statique, mais la base de code centrale conserve encore l’architecture historique qui chargeait dynamiquement des formulae basées sur un DSL sous forme de code Ruby contrôlé par l’utilisateur

Surfaces d’attaque examinées pendant l’audit

  • Vérifier si un acteur local pouvait provoquer l’exécution inattendue du DSL d’une formula sans brew install explicite
  • Examiner si une évaluation inattendue des formulae d’un tap pouvait se produire même lorsque l’utilisateur exécute seulement brew tap
  • Étudier s’il était possible de provoquer une confusion ou une collision d’espaces de noms afin que brew install foo installe une formula différente de celle attendue
  • Vérifier aussi si une formula installée localement pouvait contourner ou affaiblir discrètement les mécanismes d’isolation des builds de Homebrew
  • Côté CI/CD, la question centrale était de savoir si un acteur à faibles privilèges pouvait pivoter vers des privilèges plus élevés, polluer des builds de bottles ou créer de la persistance

Problèmes découverts dans le CLI brew

  • Dans la base de code du CLI brew, des problèmes susceptibles d’affaiblir les propriétés d’intégrité et d’isolation propres aux formulae ont été découverts
  • Des chemins permettant de charger des formulae depuis des sources inattendues, comme des URL distantes, ont également été identifiés
  • Les principaux constats sont les suivants
    • TOB-BREW-2 : une formula pouvait modifier la configuration du sandbox par injection de chaînes, ce qui pouvait mener à une évasion du sandbox
    • TOB-BREW-5 : Homebrew utilisait une fonction de hachage MD5 susceptible de collisions dans l’espace de noms synthétique FormulaNamespace, permettant à un attaquant de provoquer une confusion à l’exécution entre formulae
    • TOB-BREW-8 : une formula pouvait inclure discrètement des ressources réseau dans le build sans les déclarer dans une stanza resource
    • TOB-BREW-11 : une formula pouvait utiliser un pivot via socket sur macOS pour sortir du sandbox de build
    • TOB-BREW-12 : une formula pouvait réaliser une élévation de privilèges opportuniste via un ancien jeton sudo encore actif de l’utilisateur
    • TOB-BREW-13 : brew install pouvait être amené à installer des formulae depuis des URL non locales utilisant tout protocole pris en charge par la version de curl employée, comme SFTP ou SCP
  • Homebrew/brew est largement testé, mais sa grande surface API/CLI et ses contrats informels de comportement local laissent de nombreuses possibilités à un attaquant pour trouver des chemins d’exécution de code local hors du sandbox
  • Ces chemins ne brisent pas nécessairement l’hypothèse de sécurité centrale de Homebrew, qui suppose des formulae fiables, mais ils peuvent être exploités via des formulae malveillantes ou un chargement inattendu de formulae à partir d’entrées insuffisamment affinées

Problèmes découverts dans la CI/CD de Homebrew

  • Des problèmes susceptibles d’affaiblir l’intégrité de l’exécution CI/CD ont aussi été découverts dans les workflows et actions CI/CD de Homebrew
  • La possibilité pour un utilisateur à faibles privilèges de pivoter vers une position à privilèges plus élevés ou d’obtenir de la persistance sur des runners GitHub Actions auto-hébergés de Homebrew a été identifiée
  • Les principaux constats sont les suivants
    • TOB-BREW-18 : plusieurs workflows CI/CD utilisaient le déclencheur pull_request_target, permettant à des pull requests tierces d’exécuter du code dans le contexte du dépôt upstream de Homebrew, ce qui pouvait mener à l’exposition d’identifiants ou à la falsification de builds de bottles
    • TOB-BREW-23 : plusieurs workflows CI/CD autorisaient l’injection shell via des entrées workflow_dispatch non validées, permettant un déplacement vertical à des utilisateurs à faibles privilèges qui ne pouvaient pas modifier les workflows mais pouvaient les exécuter
  • Outre les problèmes propres à la CI/CD, certains constats liés à brew étaient importants dans l’environnement CI/CD
    • TOB-BREW-6 : le manque de sandboxing et d’isolation lors de l’extraction d’archives pouvait permettre à un acteur CI à faibles privilèges de faire extraire des formulae ou du code exécutable chargés et exécutés automatiquement, puis de pivoter vers un contexte à privilèges plus élevés
    • TOB-BREW-13 : il pouvait être exploité pour faire installer via brew install une formula absente du contexte de confiance préconfiguré de la CI, entraînant une exécution de code arbitraire et un pivot de privilèges
  • La CI/CD de Homebrew est mature et efficace pour réduire les points d’intervention humaine dans le cycle de vie des paquets, mais elle s’appuie sur des schémas de vulnérabilités dus à des usages abusifs courants dans les workflows GitHub Actions
    • Déclencheurs de workflows dangereux
    • Mélange de configuration, de code et de données via l’expansion de templates
  • Ces schémas ne permettent pas nécessairement à un acteur entièrement externe d’obtenir de la persistance ou de pivoter, mais ils peuvent être utilisés par un interne à faibles privilèges, comme un maintainer malveillant, pour affaiblir les hypothèses d’intégrité et d’isolation de la CI/CD

Pourquoi l’audit des gestionnaires de paquets est difficile

  • Les écosystèmes de gestion de paquets comme Homebrew installent et exécutent par conception du code tiers arbitraire, ce qui rend les frontières d’audit délicates
  • La distinction entre exécution de code attendue et exécution de code inattendue est elle aussi généralement informelle et définie de façon souple
  • Dans Homebrew, ce problème est encore plus marqué parce que le format de transport des paquets, la formula, est lui-même du code Ruby exécutable
  • Pendant l’audit, Trail of Bits a travaillé en étroite collaboration avec les maintainers de Homebrew, le PLC de Homebrew et Patrick Linnane, responsable sécurité de Homebrew

1 commentaires

 
GN⁺ 2024-07-31
Avis sur Hacker News
  • Je suis l’auteur de ce billet et l’une des personnes ayant participé à l’audit, donc je peux répondre aux questions.
    Si le rapport d’audit lui-même est difficile à trouver parce que c’est un lien indirect, j’en laisse aussi une copie ici : https://github.com/trailofbits/publications/blob/eb9344f2261...

  • Excellent travail, et c’est exactement le type d’examen systématique que je cherchais pour ce genre de solution open source.
    Ce n’est probablement pas le cœur de la revue de code, mais je serais curieux d’avoir votre avis sur les problèmes plus généraux de cycle de vie de la supply chain inhérents aux plateformes open source de gestion de paquets. Les points clés sont de savoir si les procédures de vérification garantissant qu’une nouvelle formula pointe vers la bonne source d’origine sont adéquates, comment un utilisateur peut être certain que brew update référence toujours une source de confiance, ce qui se passe si un domaine est détourné, et à quelle vitesse l’équipe peut réagir à une source non fiable dans une formula.
    Tous ces problèmes ne sont pas forcément à résoudre par Homebrew, mais ce sont des considérations importantes à l’échelle de l’écosystème. winget et choco ont les mêmes problèmes, tandis qu’ils sont moins présents dans des dépôts bénéficiant d’un support commercial comme apt ou yum. Pour moi, et pour beaucoup d’administrateurs, c’est aussi une grande inquiétude lorsqu’il s’agit de gérer le Windows Store.
    Enfin, si l’équipe Homebrew lit ceci, des alertes de vulnérabilités à la manière de npm seraient vraiment bienvenues.

    • Ce problème est particulièrement sérieux lorsque des gestionnaires de paquets sont utilisés en environnement de production ou dans des pipelines CI/CD.
      Il existe déjà suffisamment de cas publics où des personnes liées au Parti communiste chinois ont obtenu des droits de pull request sur des paquets critiques, et je pense qu’il y a encore plus de cas non publics ou étouffés. Le simple fait que la propriété d’un paquet passe d’une entité réputée à un particulier moins connu est évidemment préoccupant.
      En tant qu’ancien ingénieur logiciel / engineering manager devenu VC, je me demande s’il existe des startups ou des entreprises commerciales qui fournissent ce type de garanties. Mais je crains aussi que le marché pour résoudre ce problème ne soit pas assez grand pour en faire une activité indépendante.
  • Avant de passer à Nix, j’utilisais MacPorts parce que Homebrew fonctionnait à l’époque de manière assez atypique. Il ne marchait pas en configuration multi-utilisateur, possédait /usr/local, et l’absence de mises à jour automatiques et de gestion des versions causait beaucoup de problèmes du type « ça marche sur ma machine ».
    Ce qui m’a toujours mis mal à l’aise avec Homebrew, ce n’était pas Git, mais le fait de pouvoir utiliser une URL GitHub comme une sorte de paquet temporaire. Je me demande si TOB-BREW-13 fonctionnait de cette façon. Cette fonctionnalité a toujours eu l’air d’un incident de sécurité en attente de se produire.
    Quoi qu’il en soit, j’aimerais aussi voir un audit de Nix sur macOS. Je suis particulièrement curieux de savoir s’il existe des failles dans le fonctionnement de nix develop et des commandes associées.

    • C’est amusant, moi aussi je suis passé de Homebrew à MacPorts puis à Nix.
      Homebrew collectait des données d’analyse et cassait trop souvent les versions. MacPorts est beaucoup plus stable, mais certains paquets de niche ne se compilaient pas bien et j’avais des problèmes de terminfo dans tmux.
      Nix me plaît parce qu’il permet de redéfinir la plupart de ces éléments, et que je peux partager ma configuration home manager avec mon poste de travail Debian.
    • Sur macOS, Nix n’utilise pas par défaut de sandbox de build. On peut l’activer soi-même en mettant sandbox = true dans nix.conf, mais cela peut casser pas mal de choses.
      Le sandbox Nix n’a d’ailleurs pas vraiment été conçu comme une frontière de sécurité. Aucun effort n’a été fait pour empêcher les sorties de sandbox, et beaucoup d’éléments de l’hôte fuient dans l’environnement sandboxé. Pour compiler des paquets non fiables, il faut quelque chose comme gVisor ou une VM complète.
    • Nix autorise aussi github.
  • J’ai parcouru le bug de sortie de sandbox et le correctif associé : https://github.com/Homebrew/brew/pull/17700/commits/f4e5e0c7...
    Je me demande si c’est vraiment correct. On dirait qu’ils essaient d’empêcher que cela soit interpolé dans le profil sandbox et cause des problèmes, mais je ne sais pas à quel point on peut être sûr de cette liste de caractères.

    • Le message de commit aurait pu répondre à cette question, mais en réalité il ne fait que répéter ce que montre déjà le diff : « n’autorise pas les caractères spéciaux dans les chemins des règles sandbox ».
      Il n’explique pas pourquoi, ni ce qu’ont de spécial les caractères précisément interdits. Un meilleur message aurait dit quelque chose comme : « sinon, à cause de ..., on bloque certains caractères dans les chemins. Voici pourquoi ces caractères doivent être pris en compte mais pas les autres : ... ».
      Même si, au moment où l’on écrit ce code, on sait ce qu’on fait, dans un an on risque de se gratter la tête en se demandant pourquoi ce changement a été fait.
      Voici un exemple réel de bon message de commit : https://github.com/git/git/commit/92fe7c7d42cc941ed70d6fce98...
    • Si c’est ça le correctif, moi aussi je suis surpris. Une liste d’autorisation ne serait-elle pas préférable à une liste noire ?
  • Il y a quelque temps, j’ai remplacé brew par nix, et l’interface texte pourrait devenir plus conviviale pour les utilisateurs finaux.
    J’ai donc même créé un wrapper appelé « ixnay » pour pouvoir faire ixnay install aussi facilement qu’avec brew (https://github.com/pmarreck/ixnay), mais les garanties globales en valent la peine.

    • Moi aussi je trouve la ligne de commande nix pénible. Il faudra que j’essaie ça. J’aime bien la doc #help intégrée.
    • J’aurais aimé découvrir ixnay plus tôt. Moi aussi, l’expérience utilisateur m’a tellement agacé que j’ai fini par créer mon propre outil, qui s’appelle hdn : https://github.com/seasonedfish/hdn
      J’ai mentionné ixnay dans le README.
  • Par rapport à presque tous les gestionnaires de paquets Linux et *BSD, je suis un peu surpris que l’intégrité de la supply chain, qui constitue une grande surface d’attaque à faible niveau de compétence pour Homebrew, n’ait pas été beaucoup traitée.
    Les mainteneurs de Homebrew ne signent généralement pas les commits/paquets, ne signent pas les revues/fusions, ne vérifient pas les signatures des auteurs/relecteurs lors de la compilation, ne reproduisent pas les builds dans une CI contrôlée séparément, et n’imposent même pas l’authentification à deux facteurs matérielle sur GitHub.
    Le niveau de sécurité des utilisateurs de brew est lié à celui de la personne ayant aujourd’hui la pire sécurité opérationnelle parmi les centaines de mainteneurs de brew.
    En outre, comme dependabot crée automatiquement des commits, on pourrait aussi introduire un commit malveillant dans un projet externe que l’on contrôle, attendre que dependabot crée un commit de mise à jour dans Homebrew, puis le fusionner soi-même. Devenir mainteneur Homebrew ne fait pratiquement l’objet d’aucune vérification et il suffit de corriger quelques bugs faciles.
    On pourrait aussi reprendre un domaine e-mail expiré appartenant à un mainteneur, se faire envoyer les e-mails de réinitialisation de mot de passe, et compromettre le compte de quelqu’un en vacances ou en pause.
    Il est très probable qu’on puisse compromettre des milliers d’entreprises avant que quelqu’un ne s’en rende compte.
    Honnêtement, je n’autoriserais jamais Brew sur des machines d’entreprise disposant de privilèges. Cela revient à donner à des centaines de personnes quelconques, ainsi qu’à quiconque exploite leur faible sécurité opérationnelle, la capacité d’exécuter du code arbitraire sur les systèmes des utilisateurs.
    Les grands gestionnaires de paquets Linux ne vont pas non plus assez loin sur des aspects comme la signature des revues, mais la plupart ont au moins des signatures de paquets au niveau des auteurs, une revue humaine, et des builds reproductibles indépendants pour beaucoup de paquets.
    Quand on voit que des cibles de grande valeur comme les administrateurs système d’entreprise autorisent souvent brew sur leur ordinateur, Brew est en bonne voie pour dépasser Crowdstrike à tout moment en matière de dommages causés par une gestion de la supply chain insuffisante.

  • Si, sur Mac, quelque chose prenait en charge PKGBUILD comme Pacman, avec des performances similaires, et que les paquets des programmes essentiels étaient correctement maintenus, il me semble qu’il y aurait beaucoup moins de compromis à accepter pour le confort d’utilisation de Mac.
    Homebrew est excellent et les formulae sont vraiment bien maintenues, mais en raison de la simplicité de PKGBUILD, de la rapidité de synchronisation, et de la charge cognitive plus faible liée au fait de ne pas devoir mémoriser plusieurs arguments et flags pour chaque gestionnaire de paquets, j’aimerais que pacman fonctionne tout simplement sur Mac.

    • Le pacman de base ne fonctionne pas comme attendu sur macOS, mais il existe des tentatives pour le faire fonctionner avec quelques modifications/hacks : https://github.com/liudongmiao/pacman, https://github.com/kladd/pacman-osx
    • Il y a déjà eu plusieurs tentatives de ce genre. Certaines fonctionnent peut-être réellement.
    • MacPorts, ce n’est pas la même chose ? Je pose sincèrement la question.
  • Je pense que le principal vecteur d’attaque est simplement qu’on peut contribuer une nouvelle formula et y glisser un nouveau paquet malveillant.
    L’équipe de maintenance est trop réduite pour auditer toutes les nouvelles formulae proposées. Je suis surpris que ce vecteur d’attaque n’ait pas été inclus dans l’audit.

    • Je ne pense pas que les reviewers actuels des formulae de Homebrew core considèrent leur équipe comme trop petite pour examiner correctement les demandes de nouvelles formulae.
      Même si c’était le cas, c’est l’une des ambiguïtés du packaging explicitement abordées dans l’article. La frontière entre l’exécution de première partie et de tierce partie est intrinsèquement floue, et il me semble qu’il y a comparativement plus de valeur sécurité à trouver les endroits où une exécution tierce peut se produire là où on ne l’attend pas, plutôt qu’à signaler toutes les conséquences évidentes du fait d’exécuter intentionnellement du code tiers.
      Cela dit, je pense que l’ensemble de l’écosystème de packaging devrait être examiné sous l’angle de ces processus d’approbation. Mais comme il s’agit de procédures humaines, cela relève davantage d’un audit de type red team que d’un audit logiciel.
    • Ce point a été noté, et les formulae ont été supposées fiables.
      « ... These avenues do not necessarily violate Homebrew’s core security assumptions (which assume trustworthy formulae),... »
    • Moi aussi, il y a quelques jours, j’ai été horrifié en voyant quelqu’un télécharger un émulateur de console appelé « Cmder ». C’est un assemblage de plusieurs outils FOSS, et il contenait littéralement environ 1 000 fichiers potentiellement malveillants : scripts PowerShell, scripts Perl, scripts Python, scripts shell, DLL, EXE, etc.
      Au final, c’était inoffensif, mais le fait que des gens clonent simplement ce genre de dépôt Git en espérant que tout se passe bien est vraiment inquiétant.
  • En voyant plusieurs TOB-BREW-n listés, je me suis demandé si c’était une sorte de numéro CVE propre à ce projet.
    Modification : ah, c’était « Trail Of Bits - homeBREW ». Mais ça semble quand même probablement correct.

    • Oui. Pour les résultats d’audit, nous utilisons la convention TOB-$PRODUCT-$XXXX. $PRODUCT est la cible de l’audit et $XXXX est un compteur unique incrémental pour chaque constat.
      À ma connaissance, beaucoup de sociétés d’audit utilisent une méthode similaire.
  • La formulation de ce billet de blog est un peu déroutante. Il est dit que l’audit a été réalisé avec Homebrew, mais comme le nom me disait quelque chose, j’ai vérifié le README de Homebrew et j’ai vu William Woodruff dans la liste des mainteneurs sur https://github.com/Homebrew/brew.
    Je me demande s’il y a une raison pour laquelle ce point n’est pas mentionné dans le billet. Je ne pense pas que cela change grand-chose, mais j’aimerais que ce soit clarifié.

    • Au moment où l’audit a été réalisé, je n’étais pas mainteneur :-)
      Pendant longtemps, j’ai été un « membre » non mainteneur du projet, une sorte de poste semi-honorifique accordé aux anciens mainteneurs qui souhaitent continuer à participer aux discussions internes et à la gouvernance. Ensuite, quelques mois après la fin de l’audit, on m’a de nouveau proposé une adhésion en raison d’un autre travail lié à Homebrew, qui n’existait même pas et n’était pas prévu avant la planification de l’audit.
      Cela figurait dans les déclarations de conflit d’intérêts que j’ai faites à la fois à l’entreprise et aux mainteneurs de Homebrew, mais je suis d’accord qu’on peut aussi le préciser dans le billet. Je vais essayer de l’ajouter aujourd’hui.
      En résumé, je n’étais pas mainteneur au moment de la réalisation de l’audit, mais je l’ai été auparavant et je le suis de nouveau aujourd’hui. L’audit a été réalisé par moi-même et mes collègues dans le cadre de notre travail professionnel.