Rapport d’audit de Homebrew
(blog.trailofbits.com)- 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é
brewpouvaient 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 jetonssudoet à la possibilité d’installer des formulae depuis des URL non locales - Côté CI/CD, le déclencheur
pull_request_targetet des entréesworkflow_dispatchnon 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é- Homebrew/actions : dépôt de GitHub Actions personnalisées utilisées dans l’ensemble de la CI/CD de Homebrew
- Homebrew/formulae.brew.sh : base de code chargée de l’index JSON des paquets installables
- Homebrew/homebrew-test-bot : routines centrales d’orchestration CI/CD et de gestion du cycle de vie de Homebrew
- 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
brewet 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 installexplicite - 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 fooinstalle 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
sudoencore actif de l’utilisateur - TOB-BREW-13 :
brew installpouvait être amené à installer des formulae depuis des URL non locales utilisant tout protocole pris en charge par la version decurlemployé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_dispatchnon validées, permettant un déplacement vertical à des utilisateurs à faibles privilèges qui ne pouvaient pas modifier les workflows mais pouvaient les exécuter
- TOB-BREW-18 : plusieurs workflows CI/CD utilisaient le déclencheur
- 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 installune 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
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 updateré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.
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 developet des commandes associées.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.
sandbox = truedansnix.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.
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.
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...
Il y a quelque temps, j’ai remplacé
brewparnix, 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 installaussi facilement qu’avec brew (https://github.com/pmarreck/ixnay), mais les garanties globales en valent la peine.#helpintégrée.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.
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.
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.
« ... These avenues do not necessarily violate Homebrew’s core security assumptions (which assume trustworthy formulae),... »
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.
TOB-$PRODUCT-$XXXX.$PRODUCTest la cible de l’audit et$XXXXest 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é.
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.