Informe de auditoría de Homebrew
(blog.trailofbits.com)- La auditoría de Trail of Bits confirmó en Homebrew, el administrador de paquetes de facto del ecosistema de desarrollo en macOS, posibilidades de ejecución de código inesperada y debilitamiento de la integridad de compilación, aunque los hallazgos no fueron de nivel crítico
- El alcance incluyó Homebrew/brew, donde está el CLI
brew, así como Homebrew/actions, Homebrew/formulae.brew.sh y Homebrew/homebrew-test-bot, examinando conjuntamente el límite entre el administrador de paquetes local y CI/CD - En
brewse identificaron problemas que podían llevar a inyección de cadenas en la configuración del sandbox, colisiones de espacios de nombres basadas en MD5, inclusión de recursos de red no declarados, pivoteo por sockets en macOS, abuso de tokens desudoy posibilidad de instalar formulas desde URL no locales - En CI/CD, el trigger
pull_request_targety entradas no validadas deworkflow_dispatchpodían abrir caminos para manipulación de builds de bottle, exposición de credenciales, escalación de privilegios y persistencia en runners self-hosted de GitHub Actions - Homebrew asume formulas confiables, pero como la propia formula es código Ruby ejecutable y la superficie de API y CLI es amplia, resulta difícil mantener de forma consistente los límites de aislamiento e integridad
Alcance y objetivos de la auditoría
- Trail of Bits realizó una auditoría de Homebrew el verano pasado
- La auditoría cubrió Homebrew/brew, donde se encuentra el CLI
brew, y tres repositorios adyacentes críticos para la seguridad- Homebrew/actions: repositorio de GitHub Actions personalizadas usado en todo el CI/CD de Homebrew
- Homebrew/formulae.brew.sh: base de código encargada del índice JSON de paquetes instalables
- Homebrew/homebrew-test-bot: rutinas centrales de orquestación y gestión del ciclo de vida del CI/CD de Homebrew
- Open Tech Fund patrocinó la auditoría como parte de sus actividades para reforzar la seguridad de componentes clave de la infraestructura de Internet
- El informe completo puede consultarse en el repositorio de publicaciones de Trail of Bits
Por qué Homebrew es importante
- Homebrew se presenta como “el administrador de paquetes que faltaba para macOS o Linux” y cumple en la práctica el papel de administrador de paquetes estándar para desarrolladores de macOS
- Procesa cientos de millones de instalaciones de paquetes al año, incluidos paquetes esenciales como Golang, Node.js y OpenSSL
- La integridad de compilación de estos paquetes está relacionada, más allá de Homebrew, con la seguridad de ecosistemas de software dependientes
- El core de Homebrew es un monolito en Ruby que proporciona el CLI
brewy una API Ruby reutilizable - Desde su inicio en 2009, Homebrew ha cambiado varias veces su estructura para mejorar la confiabilidad y usabilidad de los paquetes
- Introdujo los builds binarios llamados bottle
- Adoptó bottle como método de instalación predeterminado en lugar de builds locales desde código fuente
- Para reducir el impacto de máquinas de desarrollador comprometidas, bottle pasó a construirse solo en CI/CD
- Aunque el método de instalación se ha vuelto cada vez más estático, en el codebase central sigue presente la estructura histórica que cargaba dinámicamente formulas basadas en DSL como código Ruby controlado por el usuario
Superficie de ataque observada en la auditoría
- Se verificó si un actor local podía provocar ejecución inesperada del DSL de formula sin un
brew installexplícito - Se revisó si la simple ejecución de
brew tappor parte del usuario podía causar una evaluación inesperada de formulas del tap - Se analizó si
brew install foopodía ser inducido a instalar una formula distinta a la esperada mediante confusión o colisión de espacios de nombres - También se comprobó si una formula instalada localmente podía eludir de forma sigilosa o debilitar los mecanismos de aislamiento de build de Homebrew
- En CI/CD, la pregunta central fue si un actor con bajos privilegios podía pivotar hacia privilegios más altos, contaminar builds de bottle o establecer persistencia
Problemas encontrados en el CLI brew
- En el codebase del CLI
brewse encontraron problemas que podían debilitar las propiedades de integridad y aislamiento por formula - También se confirmaron rutas por las que una formula podía cargarse desde orígenes inesperados, como URL remotas
- Los hallazgos principales fueron los siguientes
- TOB-BREW-2: una formula podía modificar la configuración del sandbox mediante inyección de cadenas, lo que podía derivar en escape del sandbox
- TOB-BREW-5: Homebrew usa una función hash MD5 con posibilidad de colisión para el espacio de nombres sintético
FormulaNamespace, lo que podía permitir a un atacante inducir confusión en tiempo de ejecución entre formulas - TOB-BREW-8: una formula podía incluir de forma encubierta recursos de red en el build sin declararlos en la stanza
resource - TOB-BREW-11: una formula podía salir del sandbox de build en macOS usando pivoteo por sockets
- TOB-BREW-12: una formula podía realizar escalación oportunista de privilegios mediante un token de
sudopreviamente activo del usuario - TOB-BREW-13:
brew installpodía ser inducido a instalar formulas desde URL no locales usando cualquiera de los protocolos compatibles con la versión decurlen uso, como SFTP o SCP
- Aunque Homebrew/brew está ampliamente probado, su gran superficie de API y CLI y los contratos informales de comportamiento local dejan margen para que un atacante encuentre rutas de ejecución de código local fuera del sandbox
- Estas rutas no necesariamente rompen la premisa central de seguridad de Homebrew, que asume formulas confiables, pero sí podrían explotarse con formulas maliciosas o con carga inesperada de formulas mediante entradas insuficientemente depuradas
Problemas encontrados en el CI/CD de Homebrew
- En los workflows y actions del CI/CD de Homebrew también se hallaron problemas que podían debilitar la integridad de la ejecución de CI/CD
- Se confirmó la posibilidad de que usuarios con pocos privilegios pivotaran hacia posiciones de mayor privilegio o lograran persistencia en runners self-hosted de GitHub Actions de Homebrew
- Los hallazgos principales fueron los siguientes
- TOB-BREW-18: varios workflows de CI/CD usaban el trigger
pull_request_target, permitiendo que pull requests de terceros ejecutaran código en el contexto del repositorio upstream de Homebrew, lo que podía derivar en exposición de credenciales o manipulación de builds de bottle - TOB-BREW-23: varios workflows de CI/CD permitían inyección de shell mediante entradas no validadas de
workflow_dispatch, lo que podía facilitar movimiento vertical por parte de usuarios de bajos privilegios que no pueden modificar workflows pero sí ejecutarlos
- TOB-BREW-18: varios workflows de CI/CD usaban el trigger
- Además de los problemas propios de CI/CD, algunos hallazgos relacionados con
brewtambién fueron relevantes en ese entorno- TOB-BREW-6: la falta de sandboxing y aislamiento durante la extracción de archivos podía permitir que un actor de CI con bajos privilegios provocara la extracción de formulas o código ejecutable que se cargara y ejecutara automáticamente, para luego pivotar a contextos de mayor privilegio
- TOB-BREW-13: podía aprovecharse para hacer que CI instalara con
brew installformulas fuera del contexto de confianza previamente configurado, facilitando ejecución arbitraria de código y pivot de privilegios
- El CI/CD de Homebrew es maduro y eficaz para reducir puntos de intervención humana en el ciclo de vida de los paquetes, pero depende de patrones de uso vulnerables comunes en workflows de GitHub Actions
- triggers de workflow riesgosos
- mezcla de configuración, código y datos mediante expansión de plantillas
- Estos patrones no necesariamente permiten persistencia o pivoteo por parte de un actor externo completamente ajeno, pero sí podrían ser aprovechados por un insider de bajos privilegios, como un rogue maintainer, para debilitar las suposiciones de integridad y aislamiento del CI/CD
Por qué es difícil auditar administradores de paquetes
- Los ecosistemas de administradores de paquetes como Homebrew instalan y ejecutan código arbitrario de terceros por diseño, por lo que definir el límite de auditoría es complicado
- La distinción entre ejecución de código esperada e inesperada también suele estar definida de manera informal y laxa
- En Homebrew, este problema se vuelve más evidente porque la propia formula es código Ruby ejecutable como formato de distribución del paquete
- Durante la auditoría se trabajó en estrecha colaboración con los maintainers de Homebrew, Homebrew PLC y el administrador de seguridad de Homebrew, Patrick Linnane
1 comentarios
Opiniones en Hacker News
Soy el autor de este artículo y una de las personas que participó en la auditoría, así que puedo responder preguntas.
Si les cuesta encontrar el informe de auditoría en sí porque el enlace es indirecto, dejo también una copia aquí: https://github.com/trailofbits/publications/blob/eb9344f2261...
Excelente trabajo; este tipo de revisión sistemática era justo lo que estaba buscando en una solución open source de este tipo.
Aunque probablemente no sea el foco de la revisión de código, me interesa saber qué opinan sobre los problemas generales del ciclo de vida de la cadena de suministro inherentes a las plataformas open source de gestión de paquetes. Lo clave es si los procedimientos de verificación para garantizar que una nueva formula apunte al origen correcto son adecuados, cómo puede un usuario confiar en que
brew updatesigue refiriéndose a un origen confiable, qué ocurre si un dominio es secuestrado y qué tan rápido puede responder el equipo ante un origen no confiable en una formula.No todos estos problemas son responsabilidad de Homebrew, pero son consideraciones importantes a nivel de ecosistema. winget y choco tienen el mismo problema, y es menor en repositorios con soporte comercial como apt o yum. Personalmente, y también para muchos administradores, es una gran preocupación al tratar con Windows Store.
Por último, si el equipo de Homebrew está leyendo esto, sería muy útil tener alertas de vulnerabilidades al estilo npm.
Hay suficientes casos públicos de personas vinculadas al Partido Comunista Chino que obtuvieron permisos para hacer pull requests en paquetes clave, y creo que hay muchos más casos no divulgados o encubiertos. El simple hecho de que la propiedad de un paquete pase de una entidad con buena reputación a una persona menos conocida ya es, por supuesto, motivo de preocupación.
Como exingeniero de software/gerente de ingeniería convertido en VC, me pregunto si hay startups o empresas comerciales que ofrezcan este tipo de garantías. Aunque también me preocupa que el tamaño de mercado para resolver este problema no sea suficiente como para sostener un negocio independiente.
Antes de pasarme a Nix, usaba MacPorts porque Homebrew en ese momento se comportaba de una forma bastante peculiar. No funcionaba en configuraciones multiusuario, se adueñaba de
/usr/local, y por las actualizaciones automáticas y la falta de gestión de versiones generaba muchos problemas de “en mi máquina funciona”.Lo que siempre me inquietó de Homebrew no era Git, sino que se pudieran usar URL de GitHub como paquetes temporales. Me pregunto si TOB-BREW-13 funcionaba de esa manera. Esa función siempre sonó como un incidente de seguridad esperando a ocurrir.
En cualquier caso, también me gustaría ver una auditoría de Nix en macOS. En particular, me interesa si hay fallas en la forma en que funcionan
nix developy comandos relacionados.Homebrew recopilaba analytics y las versiones se rompían con demasiada frecuencia. MacPorts es mucho más estable, pero algunos paquetes de nicho no compilaban bien y tenía problemas de terminfo en tmux.
Nix me gusta porque permite redefinir la mayoría de estas cosas y puedo compartir la configuración de home manager con mi estación de trabajo Debian.
sandbox = trueennix.conf, pero puede romper varias cosas.En realidad, el sandbox de Nix tampoco fue diseñado como un límite de seguridad. No se ha puesto esfuerzo en impedir escapes del sandbox, y muchas cosas del host se filtran al entorno aislado. Si quieres compilar paquetes no confiables, necesitas algo como gVisor o una VM completa.
Estuve revisando por encima el bug de escape del sandbox y la corrección relacionada: https://github.com/Homebrew/brew/pull/17700/commits/f4e5e0c7...
Me pregunto si esto está bien. Parece que intentan evitar que se interpole en el perfil del sandbox y cause problemas, pero no sé qué tan seguros pueden estar sobre esta lista de caracteres.
No explica por qué ni qué tienen de especial los caracteres específicos que se prohibieron. Un mejor mensaje habría incluido algo como: “se bloquean ciertos caracteres en las rutas porque, de lo contrario, ...; la razón por la que hay que preocuparse por estos caracteres pero otros están bien es ...”.
Aunque hoy hayas escrito este código y sepas qué hace, cuando lo mires de nuevo dentro de un año te vas a quedar rascándote la cabeza preguntándote por qué hiciste este cambio.
Aquí hay un ejemplo real de un buen mensaje de commit: https://github.com/git/git/commit/92fe7c7d42cc941ed70d6fce98...
Hace un tiempo reemplacé
brewpornix, y la interfaz de texto podría mejorar en facilidad de uso para el usuario final.Por eso incluso hice un wrapper llamado “ixnay” para poder hacer
ixnay installtan fácil como con brew (https://github.com/pmarreck/ixnay), pero las garantías generales valen la pena.#help.Dejé una mención a ixnay en el README.
Me sorprende un poco que casi no se haya tratado la integridad de la cadena de suministro, que es una gran superficie de ataque de baja sofisticación de Homebrew en comparación con casi todos los gestores de paquetes de Linux y *BSD.
En general, los mantenedores de Homebrew no firman commits/paquetes, no firman revisiones/merges, no verifican firmas de autores/revisores al compilar, no reproducen builds en CI con controles separados y tampoco exigen autenticación de dos factores por hardware en GitHub.
El nivel de seguridad de los usuarios de brew queda atado al de la persona con peor seguridad operativa ese día entre cientos de mantenedores de brew.
Además, como dependabot crea commits automáticamente, alguien podría meter un commit malicioso en un proyecto externo que controla, esperar a que dependabot cree el commit de actualización en Homebrew y luego hacer el merge por su cuenta. Para convertirse en mantenedor de Homebrew prácticamente hay muy poca verificación, y basta con arreglar algunos bugs fáciles.
También se podría tomar control de un dominio de correo vencido de un mantenedor, enviarse a uno mismo los correos de restablecimiento de contraseña y secuestrar la cuenta de alguien que está de vacaciones o descansando.
Es muy probable que puedan comprometer miles de empresas antes de que alguien se dé cuenta.
Sinceramente, nunca permitiría Brew en equipos corporativos con privilegios. Es básicamente darle a cientos de personas aleatorias, y a cualquiera que explote su débil seguridad operativa, la capacidad de ejecutar código arbitrario en los sistemas de los usuarios.
Los principales gestores de paquetes de Linux tampoco han ido lo suficientemente lejos en aspectos como la firma de revisiones, pero la mayoría al menos tiene firma de paquetes a nivel de autor, revisión humana y builds reproducibles independientes para muchos paquetes.
Considerando que objetivos de alto valor, como administradores de sistemas corporativos, a menudo permiten brew en sus computadoras, Brew está en trayectoria de superar a Crowdstrike en cualquier momento en cuanto al daño causado por una gestión de la cadena de suministro deficiente.
Si en Mac se admitiera algo como PKGBUILD al estilo Pacman, con rendimiento similar, y los paquetes de programas esenciales estuvieran bien mantenidos, creo que habría muchos menos compromisos que aceptar por comodidad al usar Mac.
Homebrew es excelente y las formulae están realmente bien mantenidas, pero por la simplicidad de PKGBUILD, la sincronización rápida y la menor carga cognitiva de tener que recordar múltiples argumentos y flags de cada gestor de paquetes, ojalá pacman simplemente funcionara en Mac.
Creo que el principal vector de ataque es simplemente contribuir una nueva formula y colar un paquete nuevo malicioso.
El equipo de mantenedores es demasiado pequeño para auditar todas las formulae que se contribuyen. Me sorprende que este vector de ataque no se haya incluido en la auditoría.
Incluso si lo fuera, es una de las ambigüedades del empaquetado que el artículo trata explícitamente. La frontera entre ejecución de primera parte y de tercera parte es inherentemente difusa, y creo que tiene relativamente más valor de seguridad encontrar los puntos donde la ejecución de terceros puede ocurrir en lugares inesperados, en vez de señalar todas las cosas obvias que pasan cuando se ejecuta deliberadamente código de terceros.
Dicho eso, creo que el ecosistema de empaquetado en general debería revisarse respecto de estos procesos de aprobación. Pero eso trata sobre procesos humanos, así que se parece más a una auditoría de estilo red team que a una auditoría de software.
“... These avenues do not necessarily violate Homebrew’s core security assumptions (which assume trustworthy formulae),...”
Al final resultó ser inofensivo, pero da mucho miedo que la gente simplemente clone repositorios Git así y espere que todo salga bien.
Vi listados varios TOB-BREW-n y pensé que tal vez eran algo como números CVE específicos de este proyecto.
Edición: ah, era “Trail Of Bits - homeBREW”. Aun así, probablemente era correcto.
TOB-$PRODUCT-$XXXX.$PRODUCTes el objetivo auditado y$XXXXes un contador único incremental para cada hallazgo.Hasta donde sé, muchas empresas de auditoría usan un método parecido.
La redacción de esta publicación de blog me resulta un poco confusa. Dice que hicieron esta auditoría junto con Homebrew, pero como el nombre me sonaba familiar revisé el README de Homebrew y vi que William Woodruff aparece en la lista de mantenedores en https://github.com/Homebrew/brew.
Me pregunto si hay alguna razón por la que la publicación no menciona esto. No creo que cambie mucho las cosas, pero quisiera tenerlo claro.
Durante mucho tiempo fui “miembro” no mantenedor del proyecto, una especie de puesto semihonorario que se da a exmantenedores que quieren seguir participando en conversaciones internas y en la gobernanza. Más tarde, unos meses después de terminada la auditoría, me volvieron a ofrecer la membresía por otro trabajo relacionado con Homebrew que ni existía ni estaba planeado antes de planear la auditoría.
Incluí esto en las declaraciones de conflicto de intereses que hice tanto a la empresa como a los mantenedores de Homebrew, pero estoy de acuerdo en que también podría indicarse explícitamente en la publicación del blog. Intentaré agregarlo hoy.
En resumen: no era mantenedor cuando se realizó la auditoría, pero lo fui antes y actualmente también lo soy. La auditoría la realizamos mis colegas y yo como trabajo profesional.