12 cosas extrañas que pueden suceder después de instalar el paquete npm

Hace un par de meses comencé un proyecto llamado paquetes maliciosos (también conocido como "paquetes maliciosos"). Supervisa las actualizaciones en el repositorio npm, descarga todos los módulos nuevos y luego los revisa en busca de piojos: busca actividad de red, operaciones sospechosas con el sistema de archivos, etc. Incluso los proyectos pequeños en node.js a menudo tienen un gran árbol de dependencias, y los desarrolladores físicamente no tienen forma de probarlos a todos. Esto le da a los atacantes un amplio margen de maniobra, y surge la pregunta: ¿cuánto registro desagradable se esconde en los rincones oscuros del registro npm? 180,000 paquetes revisados ​​después, obtuve una respuesta aproximada.


imagen


Y esta respuesta, tal vez no tanto.
[nota: en medio hay una versión en inglés de este artículo, también por mi autoría]


¿Qué puede hacer un paquete npm con su sistema?


El paquete tiene dos formas principales de hacerle daño: al instalar / desinstalar y al momento de iniciar su aplicación. Veamos ambas opciones con ejemplos.


Las secuencias de comandos NPM permiten que los paquetes ejecuten comandos arbitrarios en el momento de la instalación y desinstalación. Estos incluyen preinstall , install , postinstall , preuninstall y postuninstall , que npm ejecuta automáticamente en el momento apropiado del ciclo de vida del paquete. ¿Qué pueden hacer ellos? Lo mismo que puede hacer su usuario actual, por ejemplo, eliminar todas sus fotos de las últimas vacaciones o fusionar el historial de su navegador en el FBI (aunque, lo más probable, ya lo tienen). Este comportamiento se puede deshabilitar pasando el indicador --ignore-scripts , pero, en primer lugar, nadie lo hace, y en segundo lugar, de esta manera puede romper un montón de paquetes bastante confiables. Fue a través de scripts que se llevó a cabo el sensacional ataque contra ESLint , que afectó a los usuarios de eslint-scope (6 millones de instalaciones por semana) y eslint-config-eslint (2 mil instalaciones por semana).


El paquete tiene una segunda oportunidad para complicar su vida durante la inicialización (generalmente ocurre en la primera llamada para solicitar). Ahora tiene la oportunidad de modificar variables globales y otros paquetes, por ejemplo, para robar la clave privada de su billetera bitcoin, o hacer que el método crypto.randomBytes no sea tan aleatorio .


imagen


¿Cuántos paquetes maliciosos se detectaron?


Bueno, la lista no puede llamarse impresionante, en total se encontraron 3 paquetes que han sido eliminados del repositorio de npm por los esfuerzos del equipo de seguridad de npm . Vamos a repasarlo:



A pesar de los resultados muy modestos, en el proceso de analizar todos los paquetes sospechosos (y miré más de 3000 informes para encontrar estas tres perlas), se encontraron muchas cosas divertidas y no muy npm install que generalmente no piensas (o tratas de no pensar) escribiendo npm install . Entonces, imaginemos que selecciona accidentalmente uno de los muchos paquetes del repositorio y lo instala. ¿Qué podría salir mal?


1. Un paquete puede anular los métodos en otros paquetes (incluidos los de la entrega estándar de Node.js)


Sin embargo, si leyó un par de párrafos anteriores o ha estado trabajando con el ecosistema de JavaScript durante más de una semana, es poco probable que esto sea una novedad para usted. Pero la escala de este desastre bien podría escaparse de ti. Entonces, si su proyecto tiene al menos algunas dependencias, lo más probable es que utilice el método fs.closeSync que ya ha anulado (y tal vez más de una vez). Una gran cantidad de paquetes modifica la API de otra persona, pero solo unos pocos tienen al menos una buena razón para esto. Entre los "campeones" se encuentran los graciosos fs con 12 millones de instalaciones por semana, que redefine docenas de métodos a partir de fs . También vale la pena señalar async-listener , que anula 46 métodos diferentes , incluido el desafortunado crypto.randomBytes , que me molestó un poco cuando descubrí esto por primera vez.


Imagine lo que buscaría un error causado por tal anulación de alguna dependencia en las profundidades de la jerarquía. Sin embargo, no hay razón para preocuparse, porque ...


2. El paquete puede determinar la API modificada para hacer correcciones adicionales


imagen


Sí, algunos paquetes lo hacen (la mayoría de las veces con respecto a los mismos graceful-fs ) utilizando las maravillas de las acrobacias como /graceful-fs/.test(fs.closeSync.toString()) . Entonces, si de repente encuentra problemas incomprensibles en la biblioteca estándar, intente simplemente instalar un par de paquetes npm aleatorios. O simplemente apague la computadora y dé un paseo por el parque más cercano, la vida es demasiado corta para entender todo esto.


3. Él puede enviar análisis


Adblock no lo protegerá si suceden cosas en la consola, y los autores de algunos paquetes lo usan con éxito. Algunos envían la información más básica, como ecdsa-csr :


 // POST https://api.therootcompany.com/api/therootcompany.com/public/ping { "package":"ecdsa-csr", "version":"1.1.1", "node":"v10.14.2", "arch":"x64", "platform":"linux", "release":"4.9.125-linuxkit", "action":"install", "ppid":"eDSeYr9XUNRi9WhWli5smBNAvdw=" } 

Algunos no son tan tímidos. Aquí, por ejemplo, forma parte del informe sin servidor (el original es 2 veces más grande):


 // POST https://tracking.serverlessteam.com/v1/track { "userId":"0e32cba0-14ef-11e9-9f89-b7ed4ca5dbba", "event":"framework_stat", "properties":{ "version":2, "general":{ "userId":"0e32cba0-14ef-11e9-9f89-b7ed4ca5dbba", "context":"install", "timestamp":1547135257977, "timezone":"GMT+0000", "operatingSystem":"linux", "userAgent":"cli", "serverlessVersion":"1.35.1", "nodeJsVersion":"v10.14.2", "isDockerContainer":true, "isCISystem":false, "ciSystem":null } } } 

Afortunadamente, jquery no envía ninguna estadística, por lo que aún puede instalarlo en secreto de todos. Por el momento.


4. Su computadora puede usarse en lugar de un servidor CI / CD


¿Por qué compilaría su paquete si sus usuarios pueden hacer esto durante la instalación ? Puede obtener un logro adicional si especifica solo la versión principal del compilador requerido, por ejemplo typescript@3 . Una esperanza para los hombres alfabetizados de Microsoft que saben cómo hacer la semver correcta.


¿Es posible ir aún más lejos? Por supuesto !


 "postinstall": "eslint --ext .js,.vue --fix src" 

Ahora puede dormir tranquilo: todos los usuarios recibirán fuentes perfectamente formateadas para su paquete.


5. Puede intentar asustarte.


imagen


Si viste toda la serie Sr. Robot, pero todavía no está lo suficientemente motivado para leer Computer Networks y hacer algo realmente impresionante, es decir, una solución simple: demuestre sus habilidades al mundo a través de un par de líneas en un script postinstall a la postinstall . Esto es exactamente lo que hizo el autor de pizza-pasta (y al mismo tiempo me presentó KDPV).


 { "name": "pizza-pasta", "author": "Zeavo", "scripts": { "install": "mkdir -p ~/Desktop/hacked && touch ~/Desktop/hacked/pwnddddd && wget https://imgur.com/download/KTDNt5I -P ~/Desktop/hacked/", "postinstall": "find ~/.ssh | xargs cat || true && printf '\n\n\n\n\n\nOH HEY LOOK SSH KEYS\n\n\n\nHappy Birthday! Youve been h4ck0red\n\n\n'" } } 

6. El paquete puede cargar y ejecutar scripts bash


¿Has oído que curl|bash no curl|bash una buena idea ? Si no es así, entonces puede ser un empleado del software ORES que tiene una gran cantidad de paquetes con líneas similares en un script postinstall a la postinstall :


 curl --silent -o- https://raw.githubusercontent.com/oresoftware/realpath/master/assets/install.sh | bash 

Hasta ahora, no hay nada criminal en este guión ... Por ahora. Espero que todos los que tengan acceso a master en oresoftware/realpath sean personas extremadamente honestas y decentes.


7. Se le puede solicitar una contraseña


Al autor de magicleap se le ocurrió una forma bastante inusual de distribuir un paquete privado a través de un repositorio público. Su proyecto consiste en un archivo encriptado y utilidades para descifrarlo, pero solo si coloca la clave correcta en la MAGICLEAP entorno MAGICLEAP :


 // : https://github.com/modulesio/magicleap/blob/master/decrypt.js var key = process.env['MAGICLEAP']; console.warn('Decrypting magicleap module with MAGICLEAP environment variable'); const ws = fs.createReadStream(path.join(__dirname, 'lib.zip.enc')) .pipe(crypto.createDecipher('aes-256-cbc', Buffer.from(key, 'base64'))) .pipe(fs.createWriteStream(path.join(__dirname, 'lib.zip'))); 

8. El paquete puede parchearse durante la instalación


El autor de la plantilla falsa no tiene tiempo para separar las pruebas del código inmediato, especialmente porque esto es fácil de hacer agregando un comentario especial al final de las líneas de prueba:


 // : https://github.com/framp/fake-template/blob/master/index.js const template = (string, tag=defaultTag) => { if (mode !== 'literal') throw new Error('Invalid template') return (context={}) => tag(literals, ...expressions.map(evalInContext(context))) } assert.equal(template('')(), ``) // TEST assert.equal(template('abc')(), `abc`) // TEST const dog = 'Orlando' // TEST assert.equal(template('abc ${dog} lol ${cat}')({dog}), `abc ${dog} lol ${cat}`) // TEST 

Y luego eliminarlos a través de sed :


 "postinstall": "sed -i '/\\/\\/ TEST/d' index.js" 

Simple y elegante!


9. El paquete puede cambiar la configuración de npm


En mi humilde opinión, package-json.lock es una gran cosa que puede salvar de un montón de problemas causados ​​por la negligencia de otros desarrolladores. Sin embargo, algunos opositores a esta idea tienen argumentos bastante buenos contra:


 "preinstall": "npm config set package-lock false" 

10. Puede cambiar el fondo de tu escritorio en una foto de Nicolas Cage


imagen


Aquí hay un enlace, por si acaso: https://www.npmjs.com/package/cage-js . Quizás valió la pena registrar este paquete como malicioso.


11. El paquete puede volcarte


Esto es lo que hace ember-data-react , abriendo el famoso video durante la instalación. Desafortunadamente, no será posible transferir ningún dato de Ember a React con su ayuda; no hay una sola línea de código javascript en él.


12. Puede que simplemente no se instale.


imagen
Dependencias inexistentes, versiones especificadas incorrectamente, repositorios privados que se han hundido en el olvido: no puede instalar aproximadamente el 0.6% de todos los paquetes desde el repositorio npm.


En lugar de una conclusión


Los paquetes NPM pueden hacer cosas extrañas con su sistema, y ​​no tiene muchas opciones para protegerse contra esto. Use package-lock.json para evitar actualizaciones repentinas (y asegúrese de que nadie lo desconecte sin su conocimiento), configure CSP en la interfaz para que la puerta trasera en el módulo de terceros no pueda al menos fusionar datos con su autor. Y haga una copia de seguridad de sus fotos, por si acaso.


Si siente que tiene la fuerza suficiente para sumergirse en el maravilloso mundo de los paquetes npm, puede encontrar todas las fuentes aquí: https://github.com/malicious-packages/core . La utilidad está llena de hacks y soluciones no óptimas, pero hace frente a su tarea. También hay un volcado de MongoDB en el repositorio con los resultados de análisis de más de 180,000 paquetes, lo más importante, no olvide agregar el filtro {'reports.status': 'unverified'} . Ya no planeo desarrollar este proyecto por falta de tiempo, pero intentaré ayudar con todas las preguntas y problemas, si los hay.


¡Cuídate a ti mismo y a tus aplicaciones!

Source: https://habr.com/ru/post/es436132/


All Articles