Skip to main content

Exploración de extensiones de los ataques de confusión de dependencias mediante alias de paquetes de npm

Escrito por
Headshot of Nishant Jain

Nishant Jain

Snyk Advisor for malicious npm package

4 de noviembre de 2021

0 minutos de lectura

Los ataques de confusión de dependencias son un tipo de ataque a la seguridad de la cadena de suministro de código abierto en el que un atacante aprovecha la forma en que los administradores de paquetes instalan dependencias. En una publicación anterior, exploramos cómo detectar y prevenir ataques de confusión de dependencias en npm para mantener la seguridad de la cadena de suministro.

En este artículo, presentaremos una extensión del problema de la confusión de dependencias que aprovecha las capacidades de alias de paquetes de npm. Esta función de alias de paquetes, tal como la ofrece y explica la aplicación de línea de comandos de npm, permite a los usuarios instalar un paquete con un alias diferente. Según la documentación oficial de npm, considera el siguiente ejemplo:

npm install my-react@npm:react

Esto crea la siguiente entrada en package.json:

dependencies: {
  “my-react”: “npm:react”
}

Las repercusiones de los alias de paquetes de npm se manifiestan en la forma en que otras herramientas relacionadas con paquetes manejan los manifiestos de paquetes y, de hecho, también afectan al propio registro oficial npmjs.org. Aunque este escenario de ataque no tiene consecuencias directas para la seguridad (porque el paquete con alias siempre descargaría la versión especificada en el comando de npm), creemos que abre más posibilidades para otros vectores de ataque.

Cómo llevar a cabo un ataque mediante alias de paquetes de npm

Reproduzcamos el impacto de los ataques mediante alias de paquetes de npm para mostrar cómo pueden generar una posible confusión de dependencias y la instalación de paquetes maliciosos no autorizados.

Empezamos por crear un paquete llamado deneuve-package-parent que instala dos versiones distintas del paquete deneuve-package-test: las versiones 1.0.0 y 1.2.0. La versión 1.0.0 se instala porque tiene como alias el nombre de un paquete inventado, deneuve-package-private, gracias a los alias de paquetes de npm.

En npmjs.com, se interpreta como una de las dependencias de deneuve-package-parent.

A continuación, se muestra el archivo package.json como referencia completa del árbol de dependencias descrito:

{
  "name": "deneuve-package-parent",
  "version": "1.2.0-beta",
  "description": "This is the parent package!",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Hello\""
  },
  "author": "deneuve@wearehackerone.com",
  "license": "ISC",
  "dependencies": {
    "deneuve-package-test": "^1.2.0",
    "deneuve-package-private": "npm:deneuve-package-test@1.0.0"
  }
}

Publicamos el paquete en npmjs y luego consultamos la lista de dependencias.

Como puedes ver, la lista de dependencias del registro npmjs muestra el alias inventado deneuve-package-private como uno de los nombres de las dependencias:

Página del paquete npm deneuve-package-parent que muestra las dependencias deneuve-package-test y deneuve-package-private

La captura de pantalla anterior muestra una dependencia llamada deneuve-package-private, que creamos como alias en nuestro package.json, y no como una dependencia real. Este alias (utilizado como nombre de paquete) no existe realmente en el registro npmjs, ¡a menos que alguien lo publique! Y es ahí donde surgen los problemas de seguridad de la cadena de suministro.

Captura de pantalla de una página de npm que muestra un paquete privado faltante y un aviso de error 404 junto a un wombat caricaturizado.

Esto plantea la pregunta: ¿qué pasaría si alguien encontrara estos paquetes con alias y luego los publicara como paquetes maliciosos en npm? Los usuarios confundidos podrían ver una dependencia en la página oficial de un paquete de npmjs e instalarla simplemente ejecutando npm install en su equipo de desarrollo:

$ npm install deneuve-package-private

Este escenario podría darse si un desarrollador decide depurar la aplicación y descargar cada biblioteca por separado. Seamos sinceros: ¿con qué frecuencia los desarrolladores verifican si el paquete que descargan es privado? Basta con un simple error o descuido, algo que puede ocurrir incluso cuando las empresas tienen políticas contra la descarga de paquetes sin ámbito.

Publicamos un paquete vacío con ese nombre en el registro npmjs. Como puedes ver, si consultas la pestaña Dependents, esta enlaza con el paquete original que lo mencionó en uno de los alias de sus dependencias:

Página del paquete npm “dene uve-package-private” que muestra una dependencia, “dene uve-package-parent”, y los detalles del paquete

Esto debería servir de alerta para cualquier herramienta de desarrollo que maneje nombres de paquetes, como el propio registro npmjs, y ayudar a garantizar que no confunda a los usuarios con respecto a esos nombres.

El hecho de que los nombres de paquetes que imitan otros con errores tipográficos sigan siendo un vector de ataque eficaz contra la cadena de suministro demuestra que incluso una mínima apariencia de legitimidad (como la que dan los alias de paquetes) puede aumentar significativamente la probabilidad de éxito de un ataque.

Antecedentes de este hallazgo

Este tipo de ataque a la cadena de suministro lo descubrimos recientemente Mario Stathako, investigador de seguridad, y yo. Lo reportamos a GitHub y npm. Soy estudiante de posgrado y he dedicado tiempo a investigar y desarrollar recursos de seguridad para programas de recompensas por errores. ¡También soy Snyk Ambassador! Mario es especialista en pruebas de penetración y participa con regularidad en competencias Capture the Flag (CTF) y programas de recompensas por errores.

La confusión de dependencias me llamó la atención porque era algo muy básico con un gran impacto. Así que Mario y yo empezamos a buscar este problema en los programas privados de HackerOne. Queríamos ver qué tan bien respondían las empresas a investigaciones populares y las mitigaban después de que transcurriera cierto tiempo. Mientras creábamos paquetes de prueba de concepto (POC) para los ataques, descubrimos un comportamiento extraño en el sitio web de NPM: la forma en que se procesaba el archivo package.json de distintos paquetes y cómo se mostraban sus dependientes y dependencias.

Protege tu organización de los riesgos de seguridad de la cadena de suministro

Snyk desarrolló y publicó una aplicación de código abierto para la línea de comandos llamada snync que te ayuda a detectar posibles ataques de confusión de dependencias y otros relacionados, y te alerta sobre ellos. Puedes conocer todos los detalles de esta herramienta en este artículo sobre cómo detectar y prevenir la confusión de dependencias en npm.

Además, Snyk Advisor es una herramienta útil para señalar problemas de seguridad en los paquetes y sus distintas versiones, e indica explícitamente si se ha descubierto que un paquete es malicioso:

Página de Snyk Advisor del paquete npm lyft-dataset-sdk, marcado como un paquete malicioso de confusión de dependencias.

Por último, te recomendamos estas lecturas complementarias sobre prácticas recomendadas para la seguridad de la cadena de suministro de código abierto:

Empieza con los desafíos de Capture the Flag

Aprende a resolver desafíos de captura la bandera con nuestro taller virtual introductorio a pedido.