Cadena de suministro
¿Qué es la confusión de dependencias?
La confusión de dependencias es un ataque en el que un build instala el paquete público de un atacante en lugar del suyo privado con el mismo nombre. Nadie comete una errata. Al atacante le basta con averiguar el nombre de un paquete interno y publicarlo en un registro público con un número de versión alto, y un build mal configurado hace el resto.
Actualizado el
Cómo funciona un ataque de confusión de dependencias
- Encuentra un nombre interno. Los nombres de paquetes privados se filtran a través de código público, bundles de JavaScript, mensajes de error y manifiestos olvidados en repositorios.
- Publica el mismo nombre públicamente. El atacante lo registra en npm, PyPI u otro registro público, con un número de versión muy alto.
- Espera a un build. Un gestor de paquetes configurado para consultar tanto el registro interno como el público encuentra dos candidatos y prefiere la versión más alta.
- Se ejecuta dentro de la empresa. El script de instalación del paquete se ejecuta en el equipo de un desarrollador o en un runner de CI, con acceso a todo lo que haya allí.
La investigación que le dio nombre
En febrero de 2021, el investigador de seguridad Alex Birsan publicó la técnica. La había utilizado para ejecutar código dentro de más de 35 organizaciones, entre ellas Apple, Microsoft y PayPal, en el marco de programas de bug bounty o con su permiso. Funcionó en los tres lenguajes que probó, y los atacantes empezaron a copiarla a los pocos días de su publicación.
Por qué ocurre
La causa raíz es un gestor de paquetes que trata varios registros como equivalentes. El ejemplo clásico es Python:
--extra-index-url de pip añade una segunda fuente junto a PyPI, y pip puede instalar el paquete público si
encuentra uno con el mismo nombre.
# Unsafe for private packages: both indexes are candidates
pip install --extra-index-url https://pypi.internal.example/simple my-internal-lib
# Safer: one index you control, which proxies public packages
pip install --index-url https://pypi.internal.example/simple my-internal-lib
npm tiene el mismo problema con los nombres internos sin ámbito, mientras que un ámbito vinculado a su registro lo evita.
# .npmrc: everything under @acme comes only from your registry
@acme:registry=https://npm.internal.example/
Cómo prevenir la confusión de dependencias
- Use una única fuente de verdad. Apunte los builds a un único registro interno que haga de proxy de los paquetes públicos, y configúrelo para que los nombres internos nunca se resuelvan públicamente.
-
Use ámbitos o espacios de nombres. Sea el propietario de un ámbito como
@acmeen el registro público y asígnelo a su registro privado. - Reserve sus nombres. Registre los nombres de sus paquetes internos en los registros públicos, para que nadie más pueda hacerlo.
-
Bloquee y verifique. Confirme un lockfile en el repositorio y use la comprobación de hashes, como
--require-hashesde pip, para que un paquete distinto haga fallar la instalación. Consulte lo que hace y lo que no hace un lockfile. - Limite a dónde pueden conectarse los builds. Si un build solo puede acceder a su registro, no puede descargar en absoluto el paquete del atacante. Consulte la política de egress de GitHub Actions.
- Compruebe qué filtra. Busque los nombres de sus paquetes internos en el código público y en los bundles de cliente.
Confusión de dependencias frente a typosquatting
El typosquatting depende de que una persona escriba mal el nombre de un paquete público. La confusión de dependencias usa el nombre exacto de un paquete privado y depende de cómo esté configurado el build. Ambos llevan al mismo punto: código del atacante ejecutándose en su build. Consulte qué es un ataque a la cadena de suministro para ver cómo encajan con otros ataques.
Cómo saber si le ha afectado
Busque nombres de paquetes internos que se hayan resuelto desde un registro público, o versiones que no existan en su registro interno. Eso es difícil de hacer solo con un lockfile, porque la pregunta es de dónde procedió realmente un paquete durante el build.
Cómo ayuda CRACI
CRACI actúa en el punto en que se descarga el paquete. Como su runner de GitHub Actions, aplica una política de egress con fuentes tipadas para los registros, de modo que un build puede limitarse a los registros que usted permita. También registra en una SBOM cada paquete que descargó cada job, para que pueda ver qué entró en un build. CRACI no detecta que un paquete sea malicioso, así que mantenga la configuración de su registro como primera línea de defensa. Consulte las buenas prácticas de seguridad de la cadena de suministro de software.
Confusión de dependencias: preguntas frecuentes
¿Qué es un ataque de confusión de dependencias?
Un ataque en el que se instala por error un paquete público con el mismo nombre que uno privado, porque el gestor de paquetes consulta ambos registros y prefiere la versión más alta.
¿En qué se diferencia la confusión de dependencias del typosquatting?
El typosquatting depende de que alguien escriba mal el nombre de un paquete público. La confusión de dependencias usa el nombre exacto de un paquete privado y depende de una configuración de build que consulta registros públicos.
¿Cómo se previene la confusión de dependencias?
Use un único registro interno, nombres de paquetes con ámbito, lockfiles con comprobación de hashes y reglas que limiten a qué registros pueden acceder sus builds. Reservar públicamente sus nombres internos también ayuda.
¿Es seguro --extra-index-url?
No para paquetes privados. Convierte ambos índices en candidatos, así que puede instalarse un paquete público con el mismo nombre. Use --index-url con un índice que usted controle.
¿Quién descubrió la confusión de dependencias?
El investigador de seguridad Alex Birsan publicó la técnica en febrero de 2021, tras utilizarla contra más de 35 organizaciones en el marco de programas de bug bounty o con su permiso.
Limite de dónde pueden descargar sus builds
Permita solo los registros que necesita un job de GitHub Actions y vea cada paquete que incorporó.
Reservar una demo