1 puntos por GN⁺ 2 시간 전 | 1 comentarios | Compartir por WhatsApp
  • CVE-2024-YIKES es un incidente en el que el secuestro de dependencias de JavaScript se propagó a las cadenas de suministro de Rust y Python
  • El phishing de left-justify filtró credenciales de .npmrc, .pypirc, Cargo y Gem
  • El build.rs malicioso de vulpine-lz4 descargó y ejecutó un script de shell en hosts de CI
  • El malware de snekpack 3.7.0 se propagó a aproximadamente 4.2 millones de equipos y agregó claves SSH y un shell reverso
  • El gusano cryptobro-9000 accidentalmente actualizó a snekpack 3.7.1, eliminando el malware

Resumen del incidente

  • CVE-2024-YIKES es un incidente de seguridad en el que una dependencia comprometida del ecosistema JavaScript llevó al robo de credenciales, que luego se expandió a un ataque a la cadena de suministro de una biblioteca de compresión de Rust y a la distribución de malware en una herramienta de compilación de Python
  • El incidente fue reportado a las 03:47 UTC, y su estado cambió a “resuelto por accidente”, mientras que la severidad pasó de “Critical → Catastrophic → Somehow Fine”
  • La duración fue de 73 horas, y los sistemas afectados siguieron figurando como “Yes”
  • La cadena de paquetes y herramientas comprometidas siguió left-justify, vulpine-lz4 y snekpack, distribuyendo malware a aproximadamente 4 millones de desarrolladores
  • Al final, un gusano separado de minería de criptomonedas, cryptobro-9000, ejecutó actualizaciones en las máquinas infectadas y elevó snekpack a una versión legítima, eliminando el malware por accidente

Desarrollo del incidente

  • Día 1: robo de credenciales desde un paquete de JavaScript

    • A las 03:14 UTC, el mantenedor de left-justify, Marcus Chen, publicó en Twitter que le habían robado su tarjeta de transporte, una laptop vieja y “algo que parecía importante y que Kubernetes vomitó”, pero eso no se vinculó de inmediato con un problema de seguridad del paquete
    • A las 09:22 UTC, Chen intentó iniciar sesión en el registro de nmp y confirmó que no tenía su llave física de 2FA; el AI Overview en la parte superior de los resultados de Google lo dirigió al sitio de phishing yubikey-official-store.net, registrado 6 horas antes
    • A las 09:31 UTC, Chen ingresó sus credenciales de nmp en ese sitio de phishing, que le agradeció la compra y prometió entrega en 3 a 5 días hábiles
    • A las 11:00 UTC, se publicó [email protected] con un changelog que decía “performance improvements”
    • Ese paquete incluía un script de postinstalación que exfiltraba .npmrc, .pypirc, ~/.cargo/credentials y ~/.gem/credentials hacia un servidor elegido por el atacante
    • A las 13:15 UTC, se abrió un ticket de soporte en left-justify con el mensaje “why is your SDK exfiltrating my .npmrc”, pero fue marcado como “low priority - user environment issue” y luego se cerró automáticamente tras 14 días sin actividad
  • Día 1: el ataque a la cadena de suministro se extiende a una biblioteca de Rust

    • Entre las credenciales filtradas estaban las del mantenedor de la biblioteca de Rust vulpine-lz4
    • vulpine-lz4 es una biblioteca para “blazingly fast Firefox-themed LZ4 decompression”; tiene 12 estrellas en GitHub, pero es una dependencia transitiva del propio cargo
    • A las 22:00 UTC, se publicó vulpine-lz4 0.4.1 con el mensaje de commit “fix: resolve edge case in streaming decompression”
    • El cambio real agregó un script build.rs que descargaba y ejecutaba un script de shell si el hostname contenía “build”, “ci”, “action”, “jenkins”, “travis” o “karen”
  • Día 2: fallan la detección y la respuesta

    • A las 08:15 UTC, la investigadora de seguridad Karen Oyelaran descubrió el commit malicioso después de que el payload se ejecutara en su laptop personal
    • Karen Oyelaran abrió un issue con “your build script downloads and runs a shell script from the internet?”, pero no recibió respuesta
    • El mantenedor legítimo había ganado €2.3 million en EuroMillions y estaba investigando granjas de cabras en Portugal
    • A las 10:00 UTC, el VP of Engineering de un cliente Fortune 500 de snekpack se enteró del incidente por una publicación de LinkedIn titulada “Is YOUR Company Affected by left-justify?”; quiso saber por qué no lo habían incluido antes, pero en realidad ya lo habían incluido antes
    • A las 10:47 UTC, el canal de Slack #incident-response se desvió momentáneamente hacia un hilo de 45 mensajes sobre si “compromised” debía escribirse con ‘z’ al estilo estadounidense
  • Día 2: se infecta la herramienta de compilación de Python snekpack

    • A las 12:33 UTC, el script de shell apuntó al pipeline de CI de snekpack para enfocarse en una víctima específica
    • snekpack es una herramienta de compilación de Python usada por el 60% de los paquetes de PyPI cuyo nombre contiene “data”
    • snekpack había incorporado vulpine-lz4 por vendor porque “Rust is memory safe”
    • A las 18:00 UTC, se lanzó snekpack 3.7.0 y el malware empezó a instalarse en máquinas de desarrolladores de todo el mundo
    • El malware añadía una clave SSH a ~/.ssh/authorized_keys, instalaba un shell reverso que solo se activaba los martes y cambiaba el shell predeterminado del usuario a fish
    • El cambio del shell predeterminado a fish fue considerado un bug
    • A las 19:45 UTC, otro investigador de seguridad publicó una entrada de blog de 14,000 palabras titulada “I found a supply chain attack and reported it to all the wrong people”, que incluía la frase “in this economy?” 7 veces
  • Día 3: parche accidental y cierre del incidente

    • A las 01:17 UTC, un desarrollador junior en Auckland descubrió el malware mientras depuraba un problema distinto y abrió un PR para revertir vulpine-lz4 dentro de snekpack
    • Ese PR requería 2 aprobaciones, pero ambos revisores estaban dormidos
    • A las 02:00 UTC, el mantenedor de left-justify recibió una YubiKey desde yubikey-official-store.net; resultó ser una memoria USB de 4 dólares con un README que decía “lol”
    • A las 06:12 UTC, un gusano separado de minería de criptomonedas, cryptobro-9000, empezó a propagarse mediante una vulnerabilidad de jsonify-extreme
    • jsonify-extreme se describe como un paquete que “makes JSON even more JSON, now with nested comment support”
    • El payload de cryptobro-9000 no tenía nada especial, pero su método de propagación incluía ejecutar npm update y pip install --upgrade en las máquinas infectadas para ampliar la superficie de ataque futura
    • A las 06:14 UTC, cryptobro-9000 actualizó por accidente snekpack a 3.7.1
    • snekpack 3.7.1 fue una versión legítima publicada por un co-mantenedor confundido, que revertía la versión vendor de vulpine-lz4 a una versión anterior
    • A las 06:15 UTC, el shell reverso de los martes se activó, pero el servidor de comando y control había sido comprometido por cryptobro-9000 y no pudo responder
    • A las 09:00 UTC, los mantenedores de snekpack publicaron un aviso de seguridad de 4 oraciones que incluía las frases “out of an abundance of caution” y “no evidence of active exploitation”
    • “no evidence of active exploitation” se consideró técnicamente cierto porque no buscaron evidencia
    • A las 11:30 UTC, un desarrollador tuiteó “I updated all my dependencies and now my terminal is in fish???” y obtuvo 47,000 likes
    • A las 14:00 UTC, las credenciales comprometidas de vulpine-lz4 fueron reemplazadas
    • El mantenedor legítimo recibió un correo en su nueva granja de cabras y respondió: “I haven't touched that repository in two years” y “I thought Cargo 2FA was optional”
    • A las 15:22 UTC, se declaró resuelto el incidente y se agendó una retrospectiva, que luego fue reprogramada tres veces

Asignación del CVE y alcance del daño

  • En la semana 6 se asignó oficialmente CVE-2024-YIKES
  • El aviso permaneció bajo embargo mientras MITRE y GitHub Security Advisories discutían la clasificación CWE
  • Para cuando el CVE se hizo público, 3 artículos en Medium y una charla en DEF CON ya habían cubierto el incidente en detalle
  • El daño total sigue siendo desconocido
  • Se estima que el número de máquinas comprometidas fue de 4.2 millones
  • También se estima en 4.2 millones el número de máquinas salvadas por el gusano de criptominería
  • El cambio neto en la postura de seguridad quedó en “incomodidad”

Causa raíz y factores contribuyentes

  • Causa raíz

    • Se consideró como causa raíz que el perro llamado Kubernetes se comió la YubiKey
  • Factores contribuyentes

    • El registro de nmp todavía permite autenticación solo con contraseña para paquetes con menos de 10 millones de descargas semanales
    • Google AI Overviews enlazó con toda confianza una URL que no debería existir
    • La filosofía de “crates pequeños” del ecosistema Rust fue replicada desde el ecosistema npm, permitiendo que paquetes como is-even-number-rs, con 3 estrellas en GitHub, terminen como dependencia transitiva cuatro niveles abajo en infraestructura crítica
    • Las herramientas de compilación de Python incorporan bibliotecas de Rust por “performance” y luego no las actualizan
    • Dependabot fusionó automáticamente PRs después de que CI pasara, y CI pasó porque el malware instaló volkswagen
    • El gusano de criptomonedas tiene mejor higiene de CI/CD que la mayoría de las startups
    • No hubo un único responsable, pero el PR de Dependabot fue aprobado por un contratista cuyo último día de trabajo era ese viernes
    • El día del incidente era martes

Medidas de mejora y opciones restantes

  • Implementar firma de artefactos era un action item del incidente de Q3 2022, pero sigue en el backlog
  • La implementación de 2FA obligatorio ya había sido solicitada, pero no ayudó
  • La auditoría de dependencias transitivas fue tachada porque había 847 objetivos
  • Fijar todas las versiones de dependencias impide recibir parches de seguridad
  • No fijar las versiones de dependencias permite ataques a la cadena de suministro
  • La opción de reescribirlo en Rust aparece tachada y apunta a vulpine-lz4
  • Las opciones restantes son esperar un gusano benévolo o considerar un cambio de carrera hacia una granja de cabras

Impacto en clientes y respuesta organizacional

  • Algunos clientes pueden haber experimentado “resultados de seguridad no óptimos”
  • Se contactó de forma proactiva a los stakeholders afectados para dar visibilidad de la situación
  • La confianza del cliente se mantuvo como “north star”
  • Se creó un grupo de trabajo cross-functional para revisar la postura de seguridad, pero todavía no ha tenido reuniones
  • Tras revisión legal, se agregó que el shell fish no es malware, aunque a veces lo parezca
  • Este informe del incidente es el tercero del trimestre
  • La solicitud de headcount del equipo de seguridad sigue en backlog desde Q1 2023

Agradecimientos

  • Karen Oyelaran detectó el problema porque su hostname coincidía con la expresión regular
  • El PR del desarrollador junior de Auckland fue aprobado 4 horas después de que el incidente ya se hubiera resuelto
  • Algunos investigadores de seguridad encontraron el problema antes, pero lo reportaron a las personas equivocadas
  • El autor de cryptobro-9000 no quiso ser identificado, pero pidió que mencionaran su SoundCloud
  • El perro llamado Kubernetes se negó a comentar
  • El equipo de seguridad, pese a todo, cumplió el SLA de este informe

1 comentarios

 
GN⁺ 2 시간 전
Opiniones de Hacker News
  • Para quienes se confundieron: este texto es una ficción bastante bien escrita sobre un incidente de cadena de suministro
    Cuando lo leí por encima, pensé que era real y me preocupó bastante, así que terminé leyéndolo con más atención :)

    • Me morí de risa con left-justify :)
    • Al principio, sinceramente no pude distinguirlo, y la sensación fue esta: https://github.com/bitcoin/bips/blob/master/bip-0042.mediawi...
    • Si buscas CVE-2024-YIKES, también aparece una galería de blogs basura hechos con IA que reescriben este texto y fingen ser totalmente serios
    • nmp
  • Me dio curiosidad la parte citada de “vulpine-lz4 con 12 estrellas en GitHub como dependencia transitiva del propio cargo”, así que saqué al tanteo algunos crates que podrían meterse en un build de cargo y que ya tienen build.rs, por lo que llamarían menos la atención: flate2, tar, curl-sys, libgit2-sys, openssl-sys, libsqlite3-sys, blake3, libz-sys, zstd-sys, cc
    De paso, si consigues acceso a xz2, también podrías contaminar rustup
    Aun así, por lo menos sí están siguiendo Cargo.lock

    • Los crates -sys son solo bindings, así que si hicieran otra cosa se vería bastante sospechoso
      Según entiendo, los demás pertenecen a maintainers principales de Rust como alexcrichton o al propio rustlang
  • Es fácil volverse cínico porque, una vez que todo pasa, el problema y la solución parecen demasiado obvios
    Pero durante mucho tiempo, y quizá incluso ahora, el credo de la cultura hacker fue move fast and break things
    Me parece bien que esté creciendo el impulso por corregir los problemas evidentes de sistemas de cadena de suministro como npm, pero me preocupa que estemos entrando en una era de nuevos problemas de seguridad provocados en gran parte por el desarrollo agéntico
    No solo por las historias de vulnerabilidades en casi todo lo que toca Mythos/Glasswing, sino porque la forma en que construimos software, incorporamos dependencias y vamos perdiendo modelos mentales humanos sobre sistemas complejos probablemente produzca mucho software e infraestructura parchados que nadie entiende de verdad
    Ojalá que dentro de unos años, al mirar este momento, no nos arrepintamos de lo ingenuos que fuimos y de no habernos preparado bien para la larga cola del desarrollo con IA, sin intentar resolver el problema rehaciendo sistemas complejos con IA
    Eso sí, el texto estuvo chistoso

    • ¿De verdad fue el credo durante tanto tiempo? Pensé que esa horrible frase la había inventado Zuckerberg
  • Como fan de Fish, esta frase me hizo sentir a la vez atacado y comprendido: “por favor, dejen claro que el shell fish no es malware, aunque a veces lo parezca”
    Más allá del shell, la parte de “la solicitud para ampliar el equipo de seguridad estaba en backlog desde el primer trimestre de 2023” también se sintió demasiado familiar

    • Como alternativa, podrías instalar figlet con apt-get o dnf y luego sobrescribir el contenido de /etc/motd con all your base are belong to us en una enorme tipografía ASCII art
  • Me reí muchísimo con la parte donde el maintainer de left-justify recibió una YubiKey de yubikey-official-store.net, y resultó ser una memoria USB de 4 dólares con “lol” escrito en el README
    Troleo total

    • Sí, estuvo buenísimo
      Me gusta que conectar un dispositivo USB enviado desde un sitio de phishing sea en sí mismo otro vector de ataque
    • Normalmente recibes mucho menos de un sitio de phishing. ¡Una memoria USB que sí funciona!
  • No era SCP de verdad, pero fue lo más parecido a SCP que he leído últimamente

    • Ah, claro, un rarísimo Supply Chain Problem (SCP)
  • Me reí fuerte con la parte de Karen :D ;)
    Me recordó un script de build basado en make que recibí al revisar el proyecto de un compañero de clase; si el hostname contenía bpavuk, intentaba hacer rm -rf en mi carpeta home
    ¡¡Eso fue en primero de secundaria!!

  • Los incidentes de cadena de suministro sí son un dolor de cabeza y tenemos que hacerlo mejor
    Personalmente, en Rust apoyo que la fundación respalde algunos crates clave para que pasen por el mismo proceso de auditoría que el propio lenguaje Rust y financie proyectos para reducir vulnerabilidades de la cadena de suministro
    No creo que la respuesta sea deshacerse de sistemas como crates o npm. crates y npm ayudan muchísimo a muchos desarrolladores

    • crates también ha hecho esfuerzos por incorporar rustsec, pero aparte de eso, me gustaría que la comunidad dejara de depender tanto de montones de dependencias pequeñas y se moviera hacia menos dependencias grandes, como tokio
    • Muchas de las crates más populares en crates.io ya son crates de primera parte ofrecidos por la organización de Rust
      Esto se pasa por alto con frecuencia cuando la gente se preocupa por el grafo de crates de Rust
      Si miras las 10 más descargadas en la portada de crates.io, la única que no fue hecha por la organización Rust o por maintainers centrales de Rust es la crate base64
    • ¿No se podría mover las crates de alto valor a la biblioteca estándar?
    • Pero, en serio, ¿de verdad hacen falta tanto npm como nmp?
    • Honestamente, pensé que ese era el objetivo final de blessed.rs
  • “El maintainer oficial ganó 2,3 millones de euros en EuroMillions y ahora está viendo cómo criar cabras en Portugal”, y “causa raíz: un perro llamado Kubernets se comió la YubiKey”
    Ah, sí. Qué irresponsable caer en ese ataque famoso de toda la vida
    Ya sabes, la técnica de “distraer a alguien con un premio de lotería y hacer que el dongle de otra persona le parezca irresistiblemente sabroso a su mascota”
    ¿Cuándo irá a aprender la gente?

  • Menos mal que no uso npm ni pip y solo uso la forma recomendada: curl ... | bash

    • Eso es curl | sudo bash
      Qué amateur