1 puntos por GN⁺ 2024-07-31 | 1 comentarios | Compartir por WhatsApp
  • 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 brew se 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 de sudo y posibilidad de instalar formulas desde URL no locales
  • En CI/CD, el trigger pull_request_target y entradas no validadas de workflow_dispatch podí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
  • 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 brew y 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 install explícito
  • Se revisó si la simple ejecución de brew tap por parte del usuario podía causar una evaluación inesperada de formulas del tap
  • Se analizó si brew install foo podí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 brew se 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 sudo previamente activo del usuario
    • TOB-BREW-13: brew install podía ser inducido a instalar formulas desde URL no locales usando cualquiera de los protocolos compatibles con la versión de curl en 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
  • Además de los problemas propios de CI/CD, algunos hallazgos relacionados con brew tambié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 install formulas 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

 
GN⁺ 2024-07-31
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 update sigue 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.

    • Este problema es especialmente grave cuando el gestor de paquetes se usa en entornos de producción o en pipelines de CI/CD.
      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 develop y comandos relacionados.

    • Me resulta gracioso porque yo también migré en el orden Homebrew -> MacPorts -> Nix.
      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.
    • En macOS, Nix no usa sandbox de compilación de forma predeterminada. Puedes activarlo manualmente poniendo sandbox = true en nix.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.
    • Nix también permite github.
  • 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.

    • El mensaje del commit podría haber respondido esa pregunta, pero en la práctica solo repite lo que ya muestra el diff: “no permitir caracteres especiales en rutas de reglas del sandbox”.
      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...
    • Si esa es la corrección, también me sorprende. ¿No sería mejor una lista de permitidos que una lista negra?
  • Hace un tiempo reemplacé brew por nix, 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 install tan fácil como con brew (https://github.com/pmarreck/ixnay), pero las garantías generales valen la pena.

    • A mí también me resulta molesta la línea de comandos de nix. Tendré que probar esto. Me gusta la documentación integrada en #help.
    • Ojalá hubiera conocido ixnay antes. A mí también me frustró la experiencia de usuario y al final terminé creando mi propia herramienta, llamada hdn: https://github.com/seasonedfish/hdn
      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.

    • El pacman básico no funciona como uno esperaría en macOS, pero hay intentos de hacerlo funcionar con algunas modificaciones/hacks: https://github.com/liudongmiao/pacman, https://github.com/kladd/pacman-osx
    • Ha habido varios intentos de este tipo. Algunos de ellos quizá incluso estén funcionando realmente.
    • ¿MacPorts no es lo mismo? Lo pregunto en serio.
  • 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.

    • No creo que los revisores actuales de Homebrew core formula consideren que su equipo sea demasiado pequeño para revisar adecuadamente las solicitudes de nuevas formulae que entran.
      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.
    • Esa parte quedó anotada, y se asumió que las formulae son confiables.
      “... These avenues do not necessarily violate Homebrew’s core security assumptions (which assume trustworthy formulae),...”
    • A mí también me dio un susto hace unos días ver que alguien descargaba un emulador de consola llamado “Cmder”. Es una colección de varias herramientas FOSS, y literalmente tenía alrededor de 1.000 archivos potencialmente maliciosos: scripts de PowerShell, scripts de Perl, scripts de Python, scripts de shell, DLL, EXE, etc.
      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.

    • Correcto. Para los hallazgos de auditoría usamos la convención TOB-$PRODUCT-$XXXX. $PRODUCT es el objetivo auditado y $XXXX es 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.

    • No era mantenedor en el momento en que hicimos la auditoría :-)
      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.