- La campaña de confusión de repositorios (repo confusion), iniciada a mediados de 2023, volvió a expandirse, y se detectaron más de 100 mil repositorios en GitHub con cargas maliciosas similares
- Los atacantes crean réplicas maliciosas parecidas a repositorios legítimos para inducir errores de los desarrolladores, combinando clonación, inserción de loaders, re-subida, forks masivos y promoción encubierta
- Al ejecutar un repositorio malicioso, tras una ofuscación en 7 etapas se descargan código Python y binarios, y se roban datos sensibles como credenciales de inicio de sesión, contraseñas del navegador y cookies
- Aunque GitHub elimine automáticamente la mayoría de los forks, siguen quedando repositorios que evaden la detección y copias subidas manualmente, por lo que aunque sobreviva solo el 1% todavía se mantienen miles de repositorios maliciosos
- El flujo del ataque se está moviendo de paquetes maliciosos en PyPI a repositorios de GitHub, convirtiendo también a la cadena de suministro de software fuera de los package managers en una superficie de ataque directa
Cómo funciona el ataque de confusión de repositorios
- La confusión de repositorios se parece a dependency confusion en que busca que el usuario descargue un repositorio malicioso en lugar del legítimo
- La diferencia está en el punto de explotación
- dependency confusion aprovecha el funcionamiento de los package managers
- la confusión de repositorios depende de que una persona elija por error un repositorio que parece similar
- En esta campaña, se dispersaron repositorios maliciosos en masa en GitHub para aumentar la probabilidad de infección
- se clonaron repositorios existentes como
TwitterFollowBot,WhatsappBOT,discord-boost-tool,Twitch-Follow-Bot - se insertó un loader de malware en las copias
- se volvieron a subir a GitHub con el mismo nombre
- cada repositorio se forkeó automáticamente miles de veces
- se promocionaron de forma encubierta en foros y Discord, entre otros
- se clonaron repositorios existentes como
Flujo tras ejecutar un repositorio malicioso
- Cuando el usuario usa un repositorio malicioso, la carga oculta deshace una ofuscación en 7 etapas
- Después descarga código Python malicioso y ejecutables binarios
- El código malicioso se basa principalmente en una versión modificada de BlackCap-Grabber
- Los objetivos incluyen credenciales de inicio de sesión de varias apps, contraseñas y cookies del navegador, y otros datos confidenciales
- Los datos robados se envían al servidor C&C (command-and-control) del atacante, y luego continúan otras actividades maliciosas
- El análisis de código relacionado puede revisarse en el technical analysis de Trend Micro
Eliminación automática de GitHub y repositorios que permanecen
- GitHub identifica la automatización y elimina rápidamente la mayoría de los repositorios forkeados
- Aun así, la detección automatizada deja pasar muchos repositorios, y los que se suben manualmente sobreviven
- Como la cadena de ataque está automatizada a gran escala, aunque quede solo el 1% eso todavía representa miles de repositorios maliciosos
- Si buscas
🔥 2024 language:pythonen GitHub, puedes ver parte de los repositorios que se están propagando actualmente - Incluyendo los repositorios ya eliminados, la escala total llega a millones
- la eliminación suele ocurrir unas horas después de la subida, lo que dificulta documentarlos
- muchos repositorios originales siguen en pie, y la eliminación apunta sobre todo al fork bomb
- por ejemplo, en la lista de repositorios de Mattia69 se ven miles de forks en el resumen, pero no aparecen en el detalle de forks
- Algunos usuarios hacen fork de repositorios maliciosos sin saberlo, lo que también genera un efecto de red secundario de ingeniería social
Cronología de la campaña
- Mayo de 2023: Phylum reportó paquetes maliciosos subidos a PyPI
- estos paquetes contenían la parte inicial de la carga actual
- se propagaban mediante llamadas
os.system("pip install package")incrustadas en forks de repositorios populares de GitHub comochatgpt-api
- Julio-agosto de 2023: varios repositorios maliciosos fueron subidos a GitHub y entregaban la carga directamente en lugar de traer paquetes desde PyPI
- fue un cambio posterior a que PyPI eliminara los paquetes maliciosos y aumentara la atención de la comunidad de seguridad
- Aliakbar Zahravi y Peter Girnus de Trend Micro publicaron un análisis técnico
- Noviembre de 2023 hasta hoy: se detectaron más de 100 mil repositorios con cargas maliciosas similares, y la cifra sigue creciendo
- Las razones por las que este método favorece a los atacantes son claras
- GitHub es tan grande que incluso una cantidad masiva de instancias sigue siendo relativamente pequeña y difícil de detectar
- a diferencia de antes, ya no intervienen los package managers, por lo que no queda como indicador un nombre explícito de paquete malicioso
- los repositorios objetivo pertenecen a nichos pequeños y de baja popularidad, lo que facilita que los desarrolladores clonen por error repositorios falsos maliciosos
Del package manager al SCM
- El cambio de paquetes maliciosos en PyPI a repositorios maliciosos en GitHub coincide con una tendencia observada en varios package managers y plataformas SCM
- A medida que la comunidad de seguridad se concentra más en los package managers, la ruta de ataque se ha movido a otro lugar
- GitHub y plataformas similares facilitan la creación automatizada de cuentas y repositorios, y ofrecen APIs convenientes y rate limits laxos que son fáciles de evadir
- Como es posible ocultarse entre innumerables repositorios, el SCM se vuelve un objetivo ideal para infectar de forma encubierta la cadena de suministro de software
- Las campañas de dependency confusion, el código malicioso en registros de paquetes y la propagación de malware mediante SCM muestran que la seguridad de la cadena de suministro de software sigue siendo débil incluso con muchas herramientas y mecanismos de seguridad
Indicadores para verificar una infección
- En código Python, se deben buscar los siguientes patrones e investigar cualquier coincidencia
exec(Fernetexec(requestsexec(__importexec(bytesexec("""\nimportexec(compile__import__("builtins").exec(
- Se debe verificar si hay repositorios locales relacionados con automatización de plataformas sociales, bots o juegos, y eliminarlos
- Si es indispensable usarlos, deben reinstalarse validando con mucho cuidado el origen o ejecutarse dentro de un sandbox
- Si existe la posibilidad de haber clonado este tipo de repositorios, debe asumirse que las siguientes cookies, credenciales y claves fueron robadas, y actuar en consecuencia
- navegadores: servicios financieros, servicios de correo, servicios de criptomonedas, Amazon, eBay, AliExpress, Facebook, Instagram, Twitter, Youtube, Discord, TikTok, Telegram, Twitch, Steam, Yahoo, ExpressVPN, Spotify, servicios de streaming
- apps: Exodus, Atomic Wallet, Guarda, Coinomi, Ethereum
- Una lista completa de checksums de archivos no es práctica de manejar, pero algunos elementos comunes pueden verse en el VirusTotal graph
- Cloudflare desactivó los registros DNS de las direcciones maliciosas detectadas después de recibir la notificación
Defensa y respuesta
- GitHub fue notificado y eliminó la mayoría de los repositorios maliciosos, pero la campaña sigue en curso
- Los ataques que buscan inyectar código malicioso en la cadena de suministro se están volviendo cada vez más comunes
- Hay muchas soluciones para detectar malware a nivel de sistema o red, pero la cadena de suministro sigue siendo una superficie de ataque grande y rentable para los atacantes
- Si encuentras un repositorio malicioso, independientemente de si forma parte de esta campaña, puedes reportarlo mediante abuse or spam report de GitHub
- Apiiro construyó un sistema de detección de malware para monitorear codebases conectados
- análisis de código basado en LLM
- descomposición del código en un grafo de flujo completo de ejecución
- motor heurístico
- decodificación, descifrado y desofuscación dinámicos
- Si no se monitorean las cargas maliciosas inyectadas, la seguridad de la organización termina dependiendo de condiciones como que los desarrolladores no elijan repositorios equivocados casi idénticos, que no exista ningún error en la configuración de CI/CD y que el código de terceros sea 100% seguro
- Más allá de la detección y recolección de vulnerabilidades convencionales, se necesita un enfoque que exponga la próxima generación de riesgos en la cadena de suministro de software y en las aplicaciones
1 comentarios
Opiniones de Hacker News
Más allá de la advertencia general de tener cuidado con el código que se trae de repositorios públicos o fuentes externas y de verificar el árbol de dependencias, me pregunto qué impacto tendría en los LLM y las herramientas de automatización entrenados con ese contenido si hubiera grandes cantidades de código malicioso en repositorios públicos.
También parece posible que, cuando herramientas como Copilot generan respuestas largas de código, alguna parte maliciosa se mezcle por casualidad.
Vulnerabilidades simples de inyección y cosas por el estilo ya se ven con frecuencia.
Puede que no sea ahora, pero en unos años parece perfectamente posible.
La IA no ofrece ninguna garantía sobre la exactitud.
Se mostró que un atacante puede tomar control de un bot de servicio conectado al espacio de conversión Hugging Face Safetensors, un servicio popular que convierte modelos de machine learning inseguros dentro del ecosistema en versiones más seguras.
Si vas a usar LLM, hay que invertir más esfuerzo en la revisión de código, y creo que ese compromiso vale la pena.
Aun así, para que derive en un incidente real suele haber dos barreras: que el generador recibe instrucciones internas para evitar ese tipo de código, y que, por la naturaleza de los LLM, es poco probable que repita tal cual la dirección del atacante real.
De todos modos, siguen existiendo diversos vectores de ataque, como bind shells, denegación de servicio y exfiltración en sitio.
GitHub está fallando de una forma similar a como falló Usenet.
Cualquiera puede crear un repositorio, y no hay nada que distinga un repositorio oficial de uno de spam.
Así como Amazon aspiró a ser “la tienda de todo” y, al chocar con que “el 90% de todo es basura”, terminó siendo una tienda donde la mayoría es basura, GitHub también tiene que decidir si su producto es “repositorios para todos” o “código confiable”.
Por ejemplo, el PG JDBC oficial no parece tener ningún elemento que un spammer no pueda reproducir; entonces, ¿cómo se puede confiar en que este no es un repositorio infectado?: https://github.com/pgjdbc
Sonatype exige demostrar la propiedad del dominio inverso usado en el
groupId, que en este caso esorg.postgresql.El método está aquí: https://central.sonatype.org/faq/how-to-set-txt-record/
Para más tranquilidad, también se puede verificar la firma GPG, ya que todos los artefactos publicados en Maven Central están firmados, aunque tiene la desventaja de que habría que conseguir la clave que Postgres usa para firmar por una vía independiente de Sonatype.
En el caso de PG, con una búsqueda rápida no encontré la clave.
GitHub tiene alrededor de 500 millones de repositorios, así que esto en realidad está bastante bien.
Un desarrollador que usaría un repositorio infectado podría encontrar de sobra otras formas de crear un producto inseguro aunque esos repositorios no existieran en GitHub.
Parece que la organización del ejemplo simplemente no lo hizo.
Los problemas de la cadena de suministro son realmente un dolor de cabeza
No apunto directamente a los lanzamientos de npm, pero estoy creando releases en npm para monitorear con socket.dev un proyecto de navegador web con virtualización ligera llamado BrowserBox
Este proyecto también tiene unas 800 dependencias contando todas las transitivas, y usa solo 19 dependencias de nivel superior; en términos del stack completo, es relativamente liviano
Ahora estoy considerando hacer snapshots de las 800 dependencias bajo el namespace
@browserboxde npm, y rastrear y parchear las vulnerabilidades que aparezcanSuena a locura, pero así está la situación; al menos de esa manera podría garantizar directamente las vulnerabilidades de la cadena de suministro del lado Node/JS dentro del nivel de seguridad de la empresa
https://socket.dev
https://github.com/BrowserBox/BrowserBox
Como el archivo de bloqueo mantiene el sha256 de todo el árbol, aunque el repositorio sea hackeado no hace falta espejearlo para evitar cambios
Fijar una versión de unos meses atrás, en lugar de la más reciente, parece un buen equilibrio para evitar CVE nuevas sin quedar atado a versiones demasiado antiguas que luego obliguen a una gran corrección de una sola vez
El número de descargas parece una métrica aceptable al compararlo con dependencias de nivel superior de propósito similar, aunque es un criterio subjetivo
Austral otorga permisos granulares a las dependencias mediante tipos lineales
Por ejemplo, una biblioteca gráfica no necesita entrada/salida de archivos, y una biblioteca de transporte de red no necesita acceso al micrófono
Es solo una mitigación, pero me gustaría verlo en otros lenguajes
Hace unos 10 años pasé de .NET a Java y me sorprendió cuánto más tiempo empecé a dedicar al infierno de dependencias; hoy, tanto en proyectos Java como Python, la cantidad de tiempo que se va en actualizaciones de vulnerabilidades y problemas de dependencias es aterradora
Creo que en .NET este problema era menor porque la adopción de la gestión automática de paquetes llegó relativamente tarde y NuGet también era bastante joven, así que en ese momento muchos proyectos aún no lo habían adoptado y existía una cultura fuerte de evitar enormes árboles de dependencias transitivas
Los problemas recientes de Boeing parecen similares
Durante las últimas décadas, al trasladar cada vez más producción a proveedores externos y enfocarse en optimizar costos, la gestión de la cadena de suministro se volvió cada vez más difícil; en el panorama general, se parece a la cultura de cadena de suministro de la ingeniería de software moderna
Cuando trabajé en una financiera que prohibía los gestores de paquetes por seguridad de la cadena de suministro, la gestión de dependencias era lo menos molesto y también había menos problemas de calidad
Hay ventajas en el código que nunca cambia a menos que lo cambies explícitamente
Implementábamos internamente muchas cosas que otros habrían tomado como paquetes; al hacer solo lo necesario y aplicar estándares de código más altos, era más fácil de entender, depurar y modificar
El costo de escribirlo por primera vez es único y se amortiza bien, pero el costo repetido de lidiar con código que intenta hacerlo todo para todos termina siendo mayor a largo plazo y normalmente se acumula
“Simple Made Easy” de Rich Hickey mostró bien este fenómeno: lo simple y lo fácil son cosas distintas, y aunque la opción simple parezca más difícil al principio, cuando se acumulan los efectos secundarios, a largo plazo se vuelve más fácil
Ya me había dado cuenta de esto al toparme por casualidad con repositorios similares
De por sí no ejecuto código de cualquier repositorio, pero ahora, aunque confíe en el repositorio y en su dueño, levanto una VM con sandbox
Hoy en día, si eres desarrollador, parece que deberías separar claramente al menos tres entornos: trabajo, hobbies y uso personal
Hay proyectos que, aunque no sean maliciosos, están mal diseñados o escritos de forma tonta
Un programa que ejecuté hace poco agregó 3 líneas a
~/.bashrcantes de que yo le pidiera hacer cualquier cosa, y me di cuenta recién varios días despuésNo entiendo qué desarrollador podría considerar eso una buena idea, así que ahora uso un sandbox cada vez que ejecuto código externo
Es mi OS de uso diario
¿De verdad hay empleadores que permiten algo así?
Me da curiosidad qué herramientas usan en el trabajo para evitar este tipo de problemas, y si están satisfechos con su configuración actual
Estoy desarrollando un SDK con muchas descargas semanales en un equipo bastante pequeño, y hemos evaluado soluciones basadas en snyk, aikido.dev, renovate, etc., pero no queda claro si ayudan con este tipo de problema
Como todavía somos un equipo pequeño, también es una carga lidiar con herramientas con muchos falsos positivos como snyk
Sonatype analiza todos los paquetes, les agrega varios metadatos y definimos políticas que se pueden usar en Firewall para filtrar el resto
Solo funciona con dependencias públicas, pero tras usarlo durante algunos años ha funcionado bastante bien
Hasta ahora no hemos tenido problemas de malware; los paquetes con vulnerabilidades conocidas no entran en nuestra base de código, y si se descubre una vulnerabilidad en algo que estamos usando, recibimos una alerta
Clasifica las vulnerabilidades de la cadena de suministro que encuentra en alcanzables, no alcanzables e indeterminadas, lo que facilita mucho la priorización, y redujo bastante el tiempo para evaluar nuevas vulnerabilidades
Los proveedores mencionados no detectan código malicioso, solo vulnerabilidades
Aunque detecten bien las vulnerabilidades, sigues sin estar protegido contra código malicioso insertado en tu base de código
Realiza análisis estático, dinámico y de metadatos, y marca paquetes riesgosos revisando más de 40 atributos, como ejecución de shell, uso de claves SSH, comunicación de red y uso de decode+eval
https://github.com/ossillate-inc/packj
Hasta ahora ha funcionado bastante bien
https://trivy.dev/
Me pregunto si la práctica de descargar scripts de instalación de shell con
curly ejecutarlos consudoterminará prontoAlgo como “para instalar nuestro software, ejecute
curl [https://somesite/install.sh](<https://somesite/install.sh>)' | sudo sh” parece encajar muy bien con el código infectado mencionado en el artículoNuestro sistema enumera cada semana alrededor de 100 patrones de los mencionados, y aproximadamente el 3% son maliciosos
Me gustaría ver que esta práctica desaparezca
npm itiene los mismos permisosEntre las herramientas comunes actuales para descargar dependencias, la única que conozco donde no se ejecuta código hostil durante la instalación o la compilación es más o menos
go getComo mínimo, necesitamos mejores herramientas para trabajar en sandboxes y así compartimentar la explosión
La forma en que ChromeOS permite que “una máquina virtual abra ventanas Wayland en el escritorio principal” es elegante, pero la última vez que lo vi, ese código no era muy limpio ni reutilizable
Es un dominio reservado para ese propósito: https://www.rfc-editor.org/rfc/rfc2606.html#section-3
.deb/.rpm/instalador”, o, en el peor de los casos, “confíe en algo empaquetado por un tercero y no por el publicador”En npm se puede mitigar la ejecución de malware con
--ignore-scriptshttps://blog.uirig.com/getting-rid-of-npm-scripts
Con suerte, quizá haga algo raro en CI y lo detecten
La verdadera solución es un sistema de reputación como https://github.com/crev-dev/cargo-crev, pero lamentablemente casi no se usa
También vale la pena prestar atención al comentario de que se necesita un Makefile
Con la aparición constante de reportes como estos, en los últimos meses he ido mejorando poco a poco la seguridad de mi entorno de desarrollo.
Uso dev containers de VSCode para desarrollar: https://code.visualstudio.com/docs/devcontainers/create-dev-...
Una vez creados, son fáciles de usar aunque no se tenga mucho conocimiento de Docker, y van bien para levantar apps web/de consola, pero cosas como Flutter o Electron resultaron difíciles.
También me acostumbré a GitHub Codespaces para proyectos pequeños: https://github.com/codespaces
Antes, en una entrevista, me tocó hacer live coding modificando un proyecto simple de Node; si fuera hoy, creo que en una situación así definitivamente usaría contenedores o Codespaces: https://www.welivesecurity.com/en/eset-research/lazarus-luri...
Para las mejores prácticas de npm, Node y Docker, leo regularmente las guías de OWASP y, en Docker, las aplico usando imágenes lo más pequeñas posible y tags de imagen explícitos: https://cheatsheetseries.owasp.org/cheatsheets/NodeJS_Docker...
Para paquetes de npm/python, antes de instalarlos reviso en socket.dev el acceso a variables de entorno, llamadas de red, ataques a la cadena de suministro, cambios recientes de propiedad del código, etc.; y, como recomienda OWASP, también se pueden deshabilitar globalmente los scripts
postinstall: https://cheatsheetseries.owasp.org/cheatsheets/NPM_Security_...Hubo un caso de hace menos de un año de un repositorio con un virus de troyano: https://github.com/orgs/community/discussions/63603
Al fin y al cabo, hizo exactamente lo que el repositorio decía que hacía.
Con solo indicar que es un repositorio oficial ya se puede atraer cierta atención.
¿Qué podría salir mal? /s
Aun así, estoy de acuerdo en que GitHub debería mostrar mejor qué repositorio es el oficial de un proyecto.