Hackers secuestran cinco versiones de la CLI de OVHcloud para distribuir malware que roba secretos

Un atacante empleó la cuenta de GitHub de un colaborador para reemplazar los archivos de descarga de cinco versiones ya existentes de la herramienta de línea de comandos de OVHcloud el lunes 19 de octubre. La cuenta había sido tomada, y los archivos nuevos eran una compilación creada para extraer secretos guardados en el disco de cualquier equipo que la ejecutase, según indicó el proveedor de nube.

Los archivos estuvieron disponibles en GitHub durante un máximo de 94 minutos, entre las 12:47 y las 14:21 UTC, y solo llegaron a quienes instalaron o actualizaron la CLI de OVHcloud en esa franja, mediante una vía que no verifica ningún hash, en macOS, Linux x86_64 o arm64, o Windows x86_64.

OVHcloud eliminó los archivos sustituidos y publicó esa misma noche una versión limpia, la v0.16.0, como release inmutable, cuyos ficheros GitHub no permite modificar. El código fuente, la etiqueta de la versión y la cadena de compilación de la empresa no se vieron afectados: la compilación maliciosa era un simple go build de un commit posterior, subido directamente a releases publicadas entre abril y septiembre.

Quién quedó expuesto

En la v0.15.0, el atacante reemplazó seis archivos: los de macOS x86_64 y arm64, los de Linux x86_64 y arm64, el de Windows x86_64 y el archivo checksums.txt, de modo que los hashes publicados coincidían con los nuevos binarios. Esos mismos seis archivos faltan ahora también en las versiones v0.11.0 a v0.14.0. Las compilaciones para Linux i386, Windows i386, Windows arm64 y WebAssembly quedaron intactas en todas las versiones.

OVHcloud señala como comprometidas las versiones v0.11.0 a v0.15.0 y como limpia la v0.10.0. Esas cinco versiones se publicaron entre el 14 de abril y el 16 de septiembre, por lo que una copia instalada antes de las 12:47 UTC del lunes y no actualizada desde entonces es la original.

Recibió un archivo sustituido quien, en esa franja y en una de esas plataformas:

  • Ejecutó el script de instalación oficial (curl -fsSL https://raw.githubusercontent.com/ovh/ovhcloud-cli/main/install.sh | sh). Descarga el archivo de la última versión y lo instala, y nunca ha comprobado un hash.
  • Descargó un archivo desde la página de release de GitHub de cualquiera de las cinco versiones.
  • Ejecutó un job de CI o un paso de compilación que obtiene el archivo desde la URL de descarga de la release sin un hash fijado.
  • Ejecutó el comando de actualización propio de la CLI desde una instalación v0.12.0, v0.13.0 o v0.14.0 en una máquina macOS o Linux donde la herramienta se había instalado mediante el script o a mano. El comando descarga el archivo y reemplaza el binario sin comprobar el hash. En una instalación por Homebrew o go install solo imprime el comando que hay que ejecutar.

No lo recibió quien:

  • Instaló con Homebrew, cuyo cask vigente durante la franja fijaba el SHA-256 original de cada archivo. Homebrew rechaza una descarga cuyo hash no coincide, así que brew install o brew upgrade habrían fallado en lugar de instalar el archivo sustituido. Algunos análisis iniciales incluyeron Homebrew entre las vías expuestas, pero The Hacker News revisó el historial de commits del tap: nada cambió entre el cask de la v0.15.0 del 16 de septiembre y el de la v0.16.0 del lunes por la noche.
  • Usó go install o compiló desde el código fuente. La etiqueta v0.15.0 sigue apuntando a su commit de septiembre, 760fd72.
  • Extrajo la imagen de Docker. Su etiqueta latest se publicó por última vez el 21 de septiembre, cuatro semanas antes del reemplazo, y no se había reconstruido hasta el martes.
  • Instaló antes de las 12:47 UTC del lunes y no actualizó durante la franja.

Cómo identificarlo

El cliente que detectó el reemplazo extrajo la información de compilación del nuevo binario v0.15.0 para Linux arm64 con go version -m, que lee el archivo sin ejecutarlo, y la publicó en un issue de GitHub. Tres elementos delatan la compilación maliciosa:

  • La línea del módulo indica v0.15.1-0.20261013083505-5ead8ef9b43d+dirty, una pseudoversión, la cadena que Go genera para una compilación de un commit sin etiqueta, en este caso uno del 13 de octubre. Una versión auténtica lleva su número de etiqueta: la compilación limpia v0.16.0 de OVHcloud indica v0.16.0+dirty.
  • El commit registrado es 5ead8ef, no 760fd72, el commit al que apunta la etiqueta v0.15.0.
  • Aparece una línea -ldflags="-s -w". La cadena de compilación de OVHcloud usa una opción de versión que Go omite de las flags registradas, por lo que una versión auténtica no muestra ninguna línea -ldflags.

La recomendación que circula de que cualquier compilación marcada +dirty, o con líneas vcs, es la maliciosa señalaría también la propia versión de OVHcloud. The Hacker News ejecutó el mismo comando sobre el binario limpio v0.16.0 para Linux x86_64: informa v0.16.0+dirty, vcs.modified=true y el commit desde el que se compiló.

El único hash publicado de un archivo sustituido es el del archivo v0.15.0 para Linux arm64:

  • SHA-256 (archivo sustituido): 3833daffcaaaab27e4e0e0833240ffcb1df8df648f4ec0bc4a75c176e28933cb
  • SHA-256 (archivo original): 5c2beb56e6d83a4b426565a1557791ef759316abcc4effb38dd627c90aeb80e0

Una compilación sin la opción de versión mostraría su versión como undefined, pero no es aconsejable ejecutar un binario sospechoso para averiguarlo.

Qué hacer

Octave Klaba, fundador de OVHcloud, escribió en X la noche del lunes que cualquier persona afectada debe cambiar todos los secretos almacenados en el disco.

La CLI guarda las credenciales de la API de OVHcloud en ~/.ovh.conf y las lee de variables de entorno, según su documentación, y el consejo abarca todo lo demás que haya en el disco, no solo esos archivos.

  • Si ejecutó una compilación sustituida, o no puede determinarlo, trate todos los secretos legibles desde esa máquina como expuestos y rótelos. OpenSourceMalware, que investigó el incidente, añade que se haga desde otra máquina.
  • Elimine el binario e instale la v0.16.0. La versión es inmutable y cuenta con una atestación de release, un registro firmado de sus archivos. Actualizar reemplaza el programa, pero no revoca una clave que ya fue copiada, por lo que la rotación debe hacerse primero.
  • Compruebe un archivo descargado contra la release con gh release verify-asset v0.16.0 FILE, como documenta GitHub.

OVHcloud no ha indicado qué archivos lee el binario, adónde los envía ni cuántas copias se descargaron, y ninguna copia de un archivo sustituido se ha analizado públicamente. La empresa ha prometido un análisis detallado del incidente en los próximos días.

Cómo ocurrió

Cualquiera con permiso de escritura en un repositorio de GitHub puede eliminar los archivos adjuntos a una release y subir otros nuevos con los mismos nombres, y la URL de descarga no cambia salvo que la inmutabilidad de releases esté activada.

Esa opción, disponible de forma general desde octubre de 2025, bloquea los archivos y la etiqueta de una release, pero solo protege las releases creadas después de activarla.

OVHcloud no la tenía activada. En una segunda publicación del lunes por la noche, citada por Next, Klaba escribió que el problema se debía a que la opción de inmutabilidad no estaba activada, por lo que un usuario con los permisos adecuados podía modificar releases existentes directamente en GitHub sin ninguna comprobación por parte de la cadena de CI/CD de la empresa. La opción ya está habilitada, y las cadenas de compilación no se vieron afectadas.

Las cinco releases antiguas ofrecen ahora solo los cuatro archivos que el atacante no tocó.

Las subidas se hicieron a través de la cuenta de un colaborador cuyo trabajo fusionado figura en el repositorio de documentación de OVHcloud y que no es miembro público de la organización, según OpenSourceMalware, que reconstruyó una cronología a partir de los registros del lado del servidor de GitHub.

El flujo de trabajo de release nunca se ejecutó: la lista de ejecuciones no muestra ningún workflow entre el 16 de octubre y el empuje de la etiqueta v0.16.0 a las 16:00 UTC del lunes. Las primeras comprobaciones no hallaron otros repositorios afectados, escribió Klaba en su primera publicación, y OVHcloud no ha explicado cómo se obtuvieron las credenciales de la cuenta.

Un job de CI de un cliente detectó el reemplazo porque fija el SHA-256 del archivo para Linux arm64 y comenzó a fallar. Al no existir un canal privado de reporte en el repositorio, el cliente abrió un issue público, según la cronología de OpenSourceMalware a las 13:50 UTC, y OVHcloud eliminó los archivos sustituidos unos treinta minutos después, a las 14:21 UTC (16:21 en París). La v0.16.0 llegó a las 17:16 UTC, publicada bajo la cuenta corporativa ovh-cds con una etiqueta firmada.

La cuestión GlassWorm

OpenSourceMalware vincula la cuenta con GlassWorm, la campaña de malware que oculta código en caracteres Unicode invisibles y obtiene su siguiente etapa del campo memo de las transacciones de una cartera de Solana. Cuatro repositorios personales de la cuenta recibieron force-push el 5 y el 6 de marzo con un commit enmendado que añadía un cargador de ese tipo, según los investigadores.

La cartera que lee ese cargador es la mencionada en la campaña ForceMemo de GlassWorm, que en marzo introdujo malware mediante force-push en cientos de repositorios de Python con tokens de GitHub robados. The Hacker News confirmó que el archivo del cargador sigue en uno de esos repositorios, con el hash que publicaron los investigadores.

Que el mismo actor hiciera ambas cosas es "nuestra inferencia", escribieron los investigadores. El vínculo es la cuenta compartida, y nada del binario de octubre se ha relacionado con GlassWorm, porque no se conservó ninguna copia.

Cybersecurity
Cybersecurity
Cybersecurity
Cybersecurity

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *