Una campaña automatizada está utilizando tokens de GitHub robados para implantar flujos de trabajo que imprimen los secretos de un repositorio en los registros de GitHub Actions, los cuales los atacantes descargan antes de eliminar las ejecuciones. Los ataques han tenido éxito en repositorios privados y entornos de GitHub Enterprise, según un análisis de la empresa de seguridad en la nube Wiz.
Una salvaguarda de GitHub que pausa las ejecuciones de flujos de trabajo sospechosas detuvo todas las ejecuciones en repositorios públicos que Wiz verificó, pero no cubre repositorios privados ni GitHub Enterprise Server.
Cada flujo de trabajo se encuentra en una nueva rama llamada ci-sync- seguida de seis caracteres aleatorios. Eliminar una rama, o la ejecución que inició, no revierte la exposición. Todos los secretos que el repositorio podía leer deben rotarse, y el token que empujó la rama debe revocarse.
Wiz ha seguido la campaña desde el 15 de septiembre y la denomina Gheist, por el user agent gheist que la herramienta de los atacantes envía con las solicitudes a la API de GitHub.
Wiz ha recuperado más de 13.500 ramas implantadas de más de 850 cuentas comprometidas, desde proyectos personales hasta repositorios privados de organizaciones empresariales. El análisis de Wiz no indica cuántas organizaciones tuvieron secretos expuestos.
En repositorios privados y en GitHub Enterprise Server, los registros de auditoría de GitHub muestran ejecuciones en las ramas implantadas que finalizan y luego son eliminadas por el user agent gheist. Los registros de AWS CloudTrail muestran que los flujos de trabajo propios de la organización también se ejecutan en esas ramas y asumen roles de AWS, una señal de que GitHub Actions se ejecutó allí sin aprobación.
En organizaciones empresariales, la herramienta alternó tokens de varios usuarios y cuentas de automatización en minutos y clonó repositorios privados antes de implantar el flujo de trabajo. Horas después, se utilizaron credenciales de nube de la misma organización para enumerar AWS Secrets Manager. El análisis de Wiz no indica de dónde provenían esas credenciales ni quién las usó.
Hasta el 24 de octubre, la campaña seguía activa y cambiando. Aproximadamente dos tercios de las cuentas involucradas ya no estaban disponibles en GitHub. Wiz informó de la actividad a GitHub y afirma que su desaparición probablemente refleja una respuesta.
Cualquier persona con acceso de escritura a un repositorio de GitHub puede leer todos los secretos configurados en él, según la documentación de GitHub. Un token robado con ese acceso es suficiente.
Para cada repositorio al que un token puede llegar, la herramienta crea una rama ci-sync- y confirma un archivo, .github/workflows/sync-check.yml, con el mensaje ci: sync config. La confirmación no está firmada e incluye el nombre del propietario del token; al empujarla se inicia el flujo de trabajo.
El flujo de trabajo imprime el entorno del trabajo y todos los secretos que el trabajo puede leer, codificados en base32. GitHub enmascara los secretos en los registros, pero su documentación indica que esto no está garantizado una vez que un valor ha sido codificado o modificado de otra forma. Wiz afirma que el texto en base32 ya no coincide con el secreto original, por lo que se imprime en su totalidad.
El flujo de trabajo establece un bloque de permisos vacío. Eso limita el GITHUB_TOKEN del trabajo, que los atacantes no necesitan, y no impide que el trabajo lea secretos.
Una versión de la herramienta también ejecuta un trabajo para cada entorno de despliegue en el repositorio, por lo que los secretos limitados a esos entornos también se imprimen. Estos suelen ser credenciales de producción, según Wiz.
Luego, la herramienta descarga el registro a través de la API de GitHub y elimina la ejecución segundos después. Debido a que los secretos salen a través de GitHub mismo, no hay un servidor de atacante ni una conexión saliente que bloquear.
Desde el 28 de julio, GitHub retiene las ejecuciones de flujos de trabajo que identifica como potencialmente maliciosas hasta que un colaborador con acceso de escritura las aprueba. GitHub dice que la retención "actualmente se aplica solo a repositorios públicos en github.com" y que GitHub Enterprise Server no la tiene en este momento.
Todas las ejecuciones públicas de Gheist que Wiz verificó, en todas las versiones de la herramienta, seguían esperando aprobación, por lo que su carga útil nunca se ejecutó.
La retención solo detecta las ejecuciones que GitHub marca. Una nueva variante de GhostAction, una campaña separada, se ejecutó en repositorios públicos hasta que GitHub comenzó a bloquearla el 9 de octubre, según una investigación de la empresa de seguridad GitGuardian. Wiz dice que Gheist es distinta de GhostAction, que utiliza archivos de flujo de trabajo diferentes.
Alrededor del 19 de octubre, una versión de la herramienta comenzó a empujar un segundo trabajo destinado a runners autoalojados, las máquinas que las organizaciones ejecutan ellas mismas para procesar trabajos de GitHub Actions. Parece dirigirse solo a repositorios que tienen registrado un runner de este tipo.
El trabajo está escrito para buscar credenciales en la máquina del runner, incluidos 31 tipos de tokens: claves privadas, entornos de procesos, credenciales de rol de instancia de AWS, archivos de credenciales del runner y el token de cuenta de servicio de Kubernetes. Wiz describe el trabajo como defectuoso, y su análisis no reporta ninguna ejecución exitosa.
Las fuentes que Wiz pudo rastrear para los tokens robados incluyen registros de infostealers y tokens expuestos en ataques anteriores de la cadena de suministro, como el compromiso de marzo del escáner de vulnerabilidades Trivy.
Otros atacantes también utilizan las mismas cuentas. El 6 de octubre, 391 cuentas, muchas de ellas también usadas por Gheist, renombraron unos 1.461 repositorios para parecer software pirateado y difundir malware. El cambio de nombre eliminó 610 de las ramas implantadas.
Algunas víctimas también parecen estar infectadas con PolinRider, un malware que los investigadores han vinculado a Corea del Norte. El 19 y 20 de octubre, tres de ellas volvieron a empujar sus commits de Gheist con un cargador añadido a un archivo vite.config.js.
Megalodon, una campaña que empujó flujos de trabajo robados de secretos a miles de repositorios de GitHub en mayo, también había afectado a 57 de las cuentas.
Cómo revisar sus repositorios
Wiz recomienda estas comprobaciones:
- Busque ramas llamadas ci-sync- seguidas de seis caracteres, donde el único cambio sea un nuevo archivo .github/workflows/sync-check.yml con el mensaje de confirmación ci: sync config.
- En los registros de auditoría de GitHub, busque ejecuciones de flujos de trabajo en ramas ci-sync-* que se eliminaron dentro de un minuto después de finalizar, y cualquier actividad del user agent gheist.
- Si sus flujos de trabajo inician sesión en un proveedor de nube con OIDC, revise los registros de auditoría de la nube en busca de asunciones de rol o intercambios de tokens cuyo sujeto incluya una rama ci-sync-. Esto funciona incluso si no recopila registros de GitHub.
- En runners autoalojados, busque los archivos .gdmp_pat, .gdmp_patg y .gdmp_sweep, y la cadena gdmp-pivot en los registros de trabajos.
OIDC permite que los flujos de trabajo inicien sesión con tokens de corta duración en lugar de claves de nube almacenadas. De forma predeterminada, el sujeto de un token incluye el nombre de la rama solo cuando el trabajo no utiliza un entorno de despliegue, según la documentación de OIDC de GitHub.
Los indicadores publicados son:
- User agent: gheist
- Rama: ^ci-sync-[0-9a-z]{6}$
- Mensaje de confirmación: ci: sync config, añadiendo solo .github/workflows/sync-check.yml
- Cadena: toJSON(secrets) }}' | base32 -w 120
- Cadena: ===== gdmp-pivot:
- Archivo: .gdmp_pat
- Archivo: .gdmp_patg
- Archivo: .gdmp_sweep
- SHA de blob de Git (flujo de trabajo simple): f3da2b8b357dcda02fd455d314be2a95007516a6
- SHA de blob de Git (versión con tiempo de espera): d09535857a741bbb976bdc084a9a021713133291
- SHA de blob de Git (versión con separador): 1dc5af9cce950aad1eb1546ecce8565b117540c4
- SHA de blob de Git (versión con trabajo autoalojado): c665b778b2d822453293003e7ca0bbb2cb08e39d
Las versiones del flujo de trabajo que enumeran los entornos de despliegue de un repositorio varían según el repositorio, por lo que no tienen un hash fijo.
Qué hacer si encuentra una rama ci-sync
Wiz aconseja estos pasos para un repositorio afectado:
- Rote todos los secretos de repositorio, organización y entorno que el repositorio pueda usar.
- Revoke los tokens que empujaron las confirmaciones y revise los dispositivos de sus propietarios en busca de infostealers.
- Si una rama ci-sync se ejecutó en un runner autoalojado, trate la máquina y su rol de instancia de nube como comprometidos.
- No apruebe las ejecuciones de sync-check retenidas y no ejecute código de ramas ci-sync.
Para hacer que un token robado sea menos útil, Wiz también recomienda estos pasos:
- Exigir revisores en entornos que contienen secretos de producción.
- Limitar las políticas de confianza de OIDC a ramas o entornos protegidos.
- Usar GitHub Apps o tokens de grano fino de corta duración en lugar de tokens de acceso personal.
- Ejecutar runners autoalojados como máquinas de corta duración sin acceso al socket de Docker ni acceso abierto a metadatos de la nube.
Un trabajo no puede leer los secretos de un entorno hasta que un revisor requerido lo aprueba, según la documentación de GitHub.


















Deja una respuesta