Esta historia comienza cuando Sébastien Lorber, mantenedor de Docusaurus, el proyecto de documentación de código abierto basado en React, nota un cambio en la solicitud de extracción en el manifiesto del paquete. Aquí está el cambio propuesto al popular paquete cliui npm:
Específicamente, llamar nuestra atención sobre el cambio de dependencias de npm que utiliza una sintaxis desconocida:
"dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
La mayoría de los desarrolladores esperarían ver un rango de versiones más pequeño en el valor de un paquete o quizás una URL Git o basada en archivos. Sin embargo, en este caso, hay una sintaxis de prefijo npm: especial. ¿Qué significa?
¿Qué es el alias de paquete npm?
El administrador de paquetes npm admite una función de alias de paquetes que permite la definición de reglas de resolución personalizadas para paquetes. Como tal, dondequiera que se haga referencia al paquete, a través del código o el archivo de bloqueo, se resolverá con el nombre y la versión especificados por el alias.
Entonces, en el caso del cambio propuesto en esta solicitud de extracción, el paquete string-width-cjs se resolverá en el paquete string-width en las versiones ^4.2.0. Esto significa que habrá una entrada de directorio node_modules para string-width-cjs pero con el contenido de string-width@^4.2.0 y un comportamiento similar en el archivo de bloqueo (package-lock.json).
El alias de paquetes es una función del administrador de paquetes de npm que se puede utilizar en casos como la compatibilidad con ESM frente a CJS.
Dicho esto, se puede abusar del alias de paquetes. En un artículo y una divulgación de seguridad que datan de 2021, Nishant Jain, embajador de Snyk, demostró cómo se podría engañar al registro oficial de npmjs para que desinformara la información de dependencia basándose en el alias de paquetes como parte de una confusión de dependencia y un problema de seguridad de la cadena de suministro.
La solicitud de extracción fue benigna y no había riesgo de un ataque a la cadena de suministro. Sin embargo, la preocupación de Sébastien por el nombre del paquete llevó al descubrimiento de un riesgo potencial de seguridad.
Para examinar la solicitud de extracción, Sébastien empleó lockfile-lint. Esta herramienta comprueba archivos de bloqueo como package-lock.json o Yarn.lock en busca de signos de manipulación, lo que garantiza que no se hayan inyectado paquetes maliciosos en lugar del paquete npm original.
Al ejecutar la herramienta se mostraron las siguientes advertencias:
npx lockfile-lint --path package-lock.json --allowed-hosts yarn npm --validate-https --validate-package-names detected resolved URL for package with a different name: string-width-cjs expected: string-width-cjs actual: string-width detected resolved URL for package with a different name: strip-ansi-cjs expected: strip-ansi-cjs actual: strip-ansi detected resolved URL for package with a different name: wrap-ansi-cjs expected: wrap-ansi-cjs actual: wrap-ansi ✖ Error: security issues detected!
Descargo de responsabilidad: lockfile-lint es una herramienta que desarrollé en 2019 después de mi publicación que reveló el problema de seguridad con los archivos de bloqueo: por qué los archivos de bloqueo npm pueden ser un punto ciego de seguridad para inyectar módulos maliciosos.
Dados los resultados anteriores de lockfile-lint, Sébastien buscó estos nombres de paquetes en npm y sorprendentemente descubrió que sí existen en el registro público de npm:
Sébastien observó que estos nombres de paquetes no solo existen en npm, sino que también exhiben características sospechosas. Los paquetes no estaban vinculados a un repositorio de código fuente público, no contenían ningún código real cuando se inspeccionaron y se publicaron de forma anónima sin ninguna información personal asociada.
Al observar el paquete npm strip-ansi-cjs, no hay un README ni un repositorio de código fuente. Sin embargo, existen muchos paquetes legítimos y populares que citan el mismo comportamiento.
De hecho, este paquete en particular es popular, como podemos ver por sus 529 dependientes (otros paquetes que dependen de este) y 7,274 descargas semanales.
Al observar el código de strip-ansi-cjs, se muestra que solo hay un archivo en este paquete, el archivo de manifiesto del paquete package.json.
Entonces, ¿por qué un paquete que no hace nada obtiene tantas descargas y por qué tantos otros paquetes dependen de él?
Inspeccionemos al autor de estos paquetes npm.
Los tres paquetes son propiedad de himanshutester002 y todos sus paquetes se publicaron el año pasado con números de versión programática. Algunas observaciones interesantes a destacar:
También puede observar que el usuario himanshutester002 no tiene información identificable en esta página de perfil de usuario en npmjs.
Anteriormente notamos que el paquete npm strip-ansi-cjs tiene más de 500 paquetes más que lo utilizan, por lo que es potencialmente un indicador positivo de popularidad. Veámoslos:
Esto puede parecer creíble por su inclusión en la lista, pero ¿lo es realmente?
Por ejemplo, nombres como clazz-transformer o react-native-multiply o quizás gh-monoproject-cli parecen legítimos, pero ¿lo son?
Aquí está la página del paquete npm react-native-multiply:
Este paquete prácticamente no tiene descargas y su autor es un usuario anónimo de npm sin información identificable. El repositorio de URL de origen al que redirige este paquete es el inexistente https://github[.]com/hasandader/react-native-multiply. El perfil de usuario de GitHub también parece muy sospechoso y carece de actividad práctica.
Si bien el paquete npm parece contener código fuente, una mirada más cercana revela que es un ejemplo de código generado para un prototipo de aplicación de "hola mundo".
También debes preguntarte, si este paquete es solo una biblioteca de multiplicación, entonces ¿por qué necesita 776 dependencias para hacer lo siguiente?
import { multiply } from 'react-native-multiply'; const result = await multiply(3, 7);
Si bien algunos bromean acerca de que JavaScript contribuye a un árbol astronómico de paquetes anidados mediante el uso excesivo de dependencias, un proyecto con 776 dependencias directas es excesivamente grande.
Entre todas estas dependencias, se encuentran los 3 paquetes npm sospechosos con los que comenzó nuestra historia: string-width-cjs, strip-ansi-cjs y wrap-ansi-cjs:
Mencionamos que una de las dependencias de strip-ansi-cjs se llamaba clazz-transformer. Veámoslo:
Expliquemos lo que está pasando aquí. El paquete npm clazz-transformer tiene un nombre intencionalmente incorrecto con el título class-transformer en su página README. Además, su repositorio de código fuente, https://github[.]com/typestack/class-transformer, no se correlaciona con el nombre del paquete, lo que genera dudas sobre su legitimidad.
El typstack/class-transformer del repositorio asociado en GitHub tiene el archivo package.json de la siguiente manera:
El archivo package.json en GitHub no muestra ninguna declaración de dependencias, sin embargo, si inspeccionamos el código fuente del paquete real en npmjs, vemos las 437 dependencias con las que está empaquetado este clazz-transformer. Nuevamente, agrupan muy convenientemente los 3 paquetes *-cjs sospechosos:
Antes de sacar más conclusiones, es importante mencionar algunas de las características de los paquetes npm que observamos anteriormente:
Nuestros pares en Sonatype han identificado previamente casos similares de inundación de registros de código abierto con paquetes. En estos casos, el objetivo final era que los desarrolladores se recompensaran con tokens Tea, que es una plataforma Web3 para monetizar software de código abierto.
Encontrar algunos archivos tea.yaml en los paquetes mencionados respalda aún más la tesis de que parte del propósito de esta campaña es extraer tokens de té mediante el uso indebido de Tea.
A principios de este año, el 14 de abril de 2024, un usuario del foro del té publicó un comentario que respalda aún más la preocupación por el abuso del té:
Antes de extenderme con mis pensamientos finales, me gustaría agradecer sinceramente a Sébastien Lorber por su mentalidad cautelosa como mantenedor y por ayudar a revelar estos hilos de un posible ataque a la cadena de suministro de npm.
En este punto, tengo gran confianza en que puedo seguir buscando agujeros en el resto de los paquetes que supuestamente dependen de string-width-cjs para encontrar indicadores muy dudosos de legitimidad auténtica.
Supongo que todos estos paquetes dependientes y aumentos de descarga tienen el único propósito de crear una legitimidad falsa para los paquetes 3 *-cjs para que, a su debido tiempo, con la víctima adecuada en juego, estos paquetes falsos instalarse y luego continuar con una nueva versión maliciosa.
Para ayudarle a mantenerse seguro mientras trabaja con software de código abierto, le recomiendo encarecidamente que adopte prácticas de seguridad y, específicamente, estos recursos educativos de seguimiento:
¿Detectamos una campaña de seguridad de la cadena de suministro en medio de su juego sucio, o se trata solo del rastro del dinero y, como tal, puede atribuirse al spam y al abuso de registros públicos como npm y GitHub para extraer tokens de té?
Sin importar cómo se desarrolle esto, mantente alerta.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3