1 puntos por GN⁺ 2024-03-01 | 1 comentarios | Compartir por WhatsApp
  • 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

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:python en 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 como chatgpt-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(Fernet
    • exec(requests
    • exec(__import
    • exec(bytes
    • exec("""\nimport
    • exec(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

 
GN⁺ 2024-03-01
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.

    • Me preocupa más que una agencia de inteligencia inserte backdoors en la salida de los LLM que el hecho de que un backdoor aparezca por casualidad en la salida de un LLM.
      Puede que no sea ahora, pero en unos años parece perfectamente posible.
    • Creo que los LLM no solo pegan código vulnerable que estaba en los datos de entrada, sino que también van a crear vulnerabilidades nuevas por su cuenta.
      La IA no ofrece ninguna garantía sobre la exactitud.
    • Acabo de publicar un tema relacionado con LLM sobre el secuestro del bot de conversión safetensors de Hugging Face: https://news.ycombinator.com/item?id=39549482
      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.
    • Sí, es un riesgo, pero es parecido al riesgo de aceptar sin revisión el PR de un colega y que entre código vulnerable copiado de algún lado.
      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.
    • La cantidad de muestras detectadas en esta campaña es tan grande que el riesgo es más realista de lo que parece.
      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

    • GitHub parece haber elegido repositorios para todos desde que la empresa empezó, hace 16 años.
    • Si es una biblioteca Java, normalmente la descargas desde Maven Central, no desde GitHub.
      Sonatype exige demostrar la propiedad del dominio inverso usado en el groupId, que en este caso es org.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.
    • Creo que no se dimensiona bien lo pequeño que es este número.
      GitHub tiene alrededor de 500 millones de repositorios, así que esto en realidad está bastante bien.
    • Más de 100 mil repositorios infectados no es bueno, pero eso no significa que GitHub haya fracasado.
      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.
    • Si demuestras la propiedad del dominio, puedes recibir una insignia de verificación en la página de la organización, lo que aumenta bastante la confianza.
      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 @browserbox de npm, y rastrear y parchear las vulnerabilidades que aparezcan
    Suena 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

    • No sé cuántas funciones similares tiene npm, pero crates.io y cargo tienen herramientas como cargo audit y cargo deny para revisar CVE en el árbol de dependencias dentro del pipeline
      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
    • La expresión “solo unas 800 dependencias” da un poco de escalofríos
      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

    • El solo hecho de decir que los desarrolladores deberían separar entornos de trabajo, hobbies y uso personal muestra que la complejidad de la vida digital ha crecido tanto que hace dudar de si será sostenible a largo plazo
    • Cada año Qubes parece una opción más razonable
    • Yo también hago esto ahora, y no solo por software potencialmente malicioso
      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 ~/.bashrc antes de que yo le pidiera hacer cualquier cosa, y me di cuenta recién varios días después
      No entiendo qué desarrollador podría considerar eso una buena idea, así que ahora uso un sandbox cada vez que ejecuto código externo
    • Suena como una buena razón para usar Qubes OS, donde todo se ejecuta básicamente dentro de una VM
      Es mi OS de uso diario
    • Me parece que no mezclar el entorno laboral con el personal es lo más básico de lo básico
      ¿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

    • En lugar de usar repositorios de GitHub directamente, usamos paquetes públicos de repositorios de paquetes comunes como NuGet, PyPI y npm, y ponemos Repository y Firewall de Sonatype como proxy entre nosotros y los repositorios de paquetes
      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
    • En el trabajo usamos Semgrep Supply Chain y estamos bastante satisfechos
      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
    • En este subhilo parece que están confundiendo mucho malware con 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
    • Estoy creando Packj, una herramienta open source para detectar paquetes PyPI/NPM/Ruby/PHP/Maven/Rust riesgosos, como paquetes públicamente maliciosos, paquetes abandonados y paquetes de typosquatting
      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
    • Vale la pena echarle un vistazo a Trivy
      Hasta ahora ha funcionado bastante bien
      https://trivy.dev/
  • Me pregunto si la práctica de descargar scripts de instalación de shell con curl y ejecutarlos con sudo terminará pronto
    Algo 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ículo

    • Como autor de este estudio, puedo confirmarlo
      Nuestro 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
    • Lamentablemente, npm i tiene los mismos permisos
      Entre 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 get
      Como 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
    • Para este tipo de ejemplos conviene usar example.com
      Es un dominio reservado para ese propósito: https://www.rfc-editor.org/rfc/rfc2606.html#section-3
    • No es particularmente peor que las alternativas realistas: “agregue un repositorio para su distribución y confíe en él”, “descargue un .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-scripts
    https://blog.uirig.com/getting-rid-of-npm-scripts

    • En cambio, el código malicioso descargado podría ejecutarse en producción
      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
    • Desde el punto de vista de seguridad, debería ser el valor predeterminado
      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

    • El repositorio afirmaba ser un ladrón de contraseñas, y si alguien lo descargó, lo descomprimió y le robó información personal y archivos, no veo cuál es el problema.
      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.

    • Quizá más adelante GitHub empiece a vender ese check azul.
      ¿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.