CERT.at Notas de Hobby Hunter: PyPI bajo ataque
Cuando termino en CERT.at, donde trabajo principalmente en nuestro sistema de notificación (si es un operador de red en Austria y recibió una notificación mal asignada sobre algunos problemas de seguridad, es posible que haya estado involucrado en eso), a veces cambio mi Hat y explore otras áreas de seguridad «cibernética», especialmente buscando paquetes maliciosos en PyPI, un repositorio de paquetes estándar de Python. El resumen breve es: hay muchos de ellos, pero tampoco entre en pánico.
Está sucediendo ahora
Comencemos con un análisis aproximado de una campaña reciente que podría denominarse «funcaptcha». Según los registros a los que pude acceder, comenzó anteayer (26 de marzo) con un paquete llamado “schubisomv3”, pero una publicación en Twitter [0] sugiere que podría haber más cuando esto llamó mi atención.
Según mis hallazgos, la primera versión del paquete se publicó alrededor de las 18:00 del 26 de marzo (todas las marcas de tiempo son UTC+1), comenzando sin ningún contenido malicioso activo, pero incluía discursos de odio y usaba el nombre de una seguridad conocida. investigador [0].
Una muestra de la primera versión del paquete “schubisomv3”
A través de múltiples iteraciones con un enfoque aparentemente de “prueba y error” (¿Has oído hablar de probar tu software localmente? ¿O en un entorno de prueba? ¿No? Lo siento, puede que sea parcial. Soy principalmente un desarrollador). Terminamos con la versión 1.10. .0 publicado alrededor de las 20:30. Usó métodos clásicos:
- el script setup.py se configuró con un comando de instalación personalizado que anula el predeterminado
- Durante la instalación en el sistema operativo Windows, se inició un subproceso con un script cifrado dentro
- el script malicioso utilizó la biblioteca de cifrado «Fernet» para evitar la desofuscación automática.
Versión final de “schubismomv3” – anulando el comando de instalación
El código ofuscado realizaba una serie de tareas típicas de los ladrones de información, como extraer cookies y contraseñas de los navegadores web, pero también buscaba extensiones de navegador y aplicaciones relacionadas con criptomonedas, documentos con nombres que indicaban que contenían información secreta (¿Nombras tu top? -¿documentos secretos algo así como “seecret”?) y así sucesivamente. Luego, toda esta información se comprime y se envía a «funcaptcha[.]ru/delivery” (de ahí el nombre de la campaña). Después pasaría algo interesante: si el script detectaba una instalación de Atomic Wallet [1], una aplicación de billetera de criptomonedas, descargó su propia versión, intentando reemplazar la original. Finalmente, se descargó el siguiente script de Python y se colocó en el directorio de inicio de Windows.
Una muestra de código desenmascarado que intenta reemplazar la aplicación original
Dejaré el análisis profundo de estos artefactos a otros. Echemos un vistazo a por qué se trata de una campaña y no de un único paquete malicioso. Tan pronto como se informó y eliminó “schubismomv3” (poco después de las 21:00, según la información que pude recopilar), PyPI se vio inundado de paquetes similares, todos mostrando la misma actividad maliciosa.
Inicialmente, el actor de amenazas utilizó nombres que no eran precisamente de marketing, como “insanepackagev1434” o “insanepackage217234234242423442983”. Pero más tarde comenzaron a intentar «corregir errores tipográficos» en paquetes populares, creando y cargando paquetes que reflejaban fielmente (pero no exactamente) los nombres de los populares.
Algunos ejemplos fueron “reqzests”, “requetsa”, “py-cordd”, “py-coqrd”, “coloramza”, “corlorama”, “capmonstercloudclouidclient”, “piolow”, “bop-utils” y muchos cientos ( !) más.
La campaña continuó hasta la madrugada del 28 de marzo, cuando los administradores de PyPI tomaron la decisión de suspender temporalmente el registro de nuevos usuarios y proyectos. [14]. Hasta entonces, se habían creado más de 500 paquetes.
No están solos…
Si analizamos los pocos meses que pasé analizando PyPI, puedo decir con confianza que la campaña “funcaptcha” podría haber sido una excepción en términos de la cantidad de paquetes maliciosos involucrados, pero no fue la única.
Observé una serie de paquetes potencialmente maliciosos, con otro caso reciente, «yocolor», que inicialmente parecía algo pequeño en PyPI, pero resultó ser una campaña significativamente más grande dirigida a repositorios en Github. [2] [3].
Otros paquetes sospechosos no hacían nada dañino, pero tampoco eran lo que querías obtener: algunos eran paquetes de prueba (generalmente se eliminan muy rápidamente), algunos eran anuncios, algunos pueden ser parte de esfuerzos de investigación.
Comando de ejemplo extraído de un paquete que no es dañino por sí solo, pero probablemente no querías compartirlo todo
…pero tampoco es motivo de pánico
Todo lo que he escrito es inquietante, pero comparativamente sencillo de captar. Los métodos son tan populares (y obvios) que me resultan algo confusos. Los actores de amenazas deben ser conscientes de que las posibilidades de comprometer con éxito sistemas del mundo real son escasas o insignificantes. El retorno de la inversión razonablemente esperado se ve superado con creces por el esfuerzo que los atacantes han puesto en estas campañas.
La campaña «funcaptcha» es un buen ejemplo: sí, su código contiene funcionalidad para filtrar datos, así como algunas técnicas más avanzadas. Pero el vector de infección inicial (suponiendo que no haya otros más sin descubrir) expone los paquetes a una rápida detección y eliminación.
Anular el comando de instalación predeterminado es una de las primeras cosas que se verifican cuando se examina un paquete, y una conexión externa durante la instalación es una actividad bastante sospechosa (aunque a menudo es un comportamiento legítimo).
Los atacantes parecían saber todo esto y no intentaron ocultarlo, lo cual es extraño, a menos que la campaña fuera sólo una cortina de humo. El primer paso se modificó ligeramente en paquetes posteriores, descargando el primer script malicioso de su dominio en lugar de incrustarlo y registrando el nombre del paquete.
Descripción de ejemplo de paquetes lanzados en etapas posteriores de la campaña “funcaptcha”: era lo que verías en PyPI. Espero que no intentes instalar dicho paquete.
Equipo de seguridad de PyPI
PyPI desempeña un papel importante a la hora de proteger su entorno de desarrollo contra este tipo de ataques. Después de algunos intentos, el índice decidió hace años no buscar proactivamente malware y, en cambio, invirtió en mejorar el manejo de los informes de abuso.
Y ellos lo hacen bien. El equipo responde muy rápidamente y, en ocasiones, elimina paquetes maliciosos en cuestión de minutos. El año pasado, PyPI alcanzó un hito importante al contratar a su primer ingeniero oficial de Seguridad y Vigilancia. [4].
Son activos y transparentes en su trabajo, realizando una auditoría de seguridad del registro. [5]explicando el proceso de denuncia de abuso [6]y, más recientemente, mejorar el canal de informes, además de lanzar una versión beta privada de la API de informes. [7].
Esto significa que PyPI, aunque está bajo constante ataque de actores de amenazas, está aprovechando el poder de muchos investigadores que buscan paquetes maliciosos. Y parece funcionar bien, al menos contra actores de amenazas que utilizan métodos conocidos.
¿Qué significa todo esto para mí?
Mi opinión personal es que la mayoría de los casos que vemos en los medios de seguridad y en las publicaciones de blogs de los investigadores sobre paquetes maliciosos no son amenazas reales en las que deberíamos pasar noches sin dormir pensando; podemos dejar esa inquietud a amenazas avanzadas como las puertas traseras en los populares bibliotecas, acciones maliciosas bien ocultas que sólo se activan en condiciones muy específicas, etc.
Las amenazas típicas que se basan en métodos obvios se parecen más a la gripe: no podemos ignorarlas, pero debemos acostumbrarnos a ellas y, lo más importante, tomar precauciones básicas.
Esto siempre depende de lo que esté tratando de proteger; no olvide pensar en su modelo de amenazas, ¡incluso si es básico!
Hay algunos consejos, útiles no sólo para entornos Python:
- Hacer. No. Descargar. Aleatorio. Cosa. Realmente, eso es lo más importante. El código malicioso suele estar oculto en paquetes de baja calidad, repositorios en Github, etc. Preste atención a lo que ejecuta en su computadora.
- Utilice dependencias acreditadas. Pero tenga cuidado: la información de los registros de paquetes, como los repositorios conectados o los nombres de mantenimiento, suele ser sólo una declaración. En su lugar, utilice servicios de reputación externos. Hay algunos gratuitos que puedes consultar (por ejemplo [8] [9]), así como servicios que ofrecen solo dependencias verificadas para descargar.
- Mantenga sus dependencias saludables. Escanéelos periódicamente en busca de vulnerabilidades conocidas (incluidas imágenes de contenedores) e instale actualizaciones de seguridad (no necesariamente completamente automatizadas, ya que abrirían la puerta a otras amenazas). Puede utilizar servicios gratuitos o de pago, y su servicio de alojamiento de origen probablemente ya tenga algo listo para una integración sencilla. Por ejemplo, puedes consultar osv.dev [10].
- Instala sólo lo que necesitas. Puedes pensar en las dependencias de tu proyecto como una lista de ingredientes: si el alimento o bebida que estás a punto de comprar tiene una larga lista de ingredientes que no entiendes, probablemente deberías pensarlo dos veces antes de comerlo. Dependencias que no necesita, dependencias que se han utilizado pero que ya no se utilizan: todas ellas aumentan innecesariamente el riesgo de un incidente.
- Piense en reducir los datos a los que tiene acceso su entorno de desarrollo. Los actores de subprocesos utilizan paquetes y repositorios maliciosos para apuntar a datos en las máquinas de los desarrolladores. Soluciones como contenedores de desarrollo [11] puede reducir el alcance potencial de una infracción.
- Supervise los entornos de prueba de la misma manera que lo haría en producción. Es posible que las amenazas avanzadas no sean fáciles de detectar localmente, pero existe la posibilidad de que revelen sus intenciones en sus entornos de prueba antes de llegar a producción. Monitorear las conexiones salientes puede resultar útil para detectarlas. Además: probablemente también desee proteger sus entornos de prueba como producción si se accede a ellos externamente. [12]y no dejar allí tus datos de producción, especialmente de antiguos clientes. [13].
Mantenerse seguro
Comencé explicando un caso del mundo PyPI, pero eso fue solo un ejemplo. Desarrollar software significa depender de dependencias externas, y es fantástico que compartamos partes comunes, especialmente cuando implementamos soluciones complejas (no implementes tu propia criptografía. Simplemente no lo hagas). Como todo, conlleva sus propios riesgos y sólo hay que ser conscientes de ellos. Y toma precauciones. Y no descargues cosas al azar.
COI
Puede buscar signos de «funcaptcha» de la siguiente manera:
- funcaptcha[.]ru
- 0c1ddd33e630f4ac684880f0e673dfa84919272494c11da0f1ec05fb4f919ce8: la primera de las aplicaciones modificadas que el script intentó inyectar
- abe19b0964daf24cd82c6db59212fd7a61c4c8335dd4a32b8e55c7c05c17220d – segunda aplicación modificada
Referencias
[0] https://x.com/_JohnHammond/status/1772704618574705057?s=20
[3] https://medium.com/@demonia/discovering-malwares-in-public-github-repositories-3e080f030ecc
[4] https://blog.pypi.org/posts/2023-08-04-pypi-hires-safety-engineer/
[5] https://blog.pypi.org/posts/2023-11-14-1-pypi-completes-first-security-audit/
[6] https://blog.pypi.org/posts/2023-09-18-inbound-malware-reporting/
[7] https://blog.pypi.org/posts/2024-03-06-malware-reporting-evolved/
[9] https://securityscorecards.dev/
[10] https://osv.dev/
[11] https://contenedores.dev/
[13] https://niebezpiecznik.pl/post/dcg-centrum-medyczne-pokazuje-jak-nie-informowac-o-kradziezy-danych-pacjentow/ (Polaco: datos de una clínica médica robados del entorno de pruebas de un proveedor con el que no han trabajado durante algunos años)