El ataque a los paquetes Laravel-Lang que demostró que ningún entorno PHP está a salvo

Entre el 22 y el 23 de mayo de 2026, un grupo identificado como TeamPCP comprometió más de 700 versiones históricas de cuatro paquetes del proyecto Laravel-Lang. El vector fue la manipulación de etiquetas Git en Composer, el gestor de dependencias de PHP. En menos de 48 horas, cualquier aplicación que instalara o actualizara esos paquetes podía estar ejecutando un ladrón de credenciales sin saberlo.

Los paquetes afectados

Los cuatro repositorios atacados forman parte del proyecto Laravel-Lang, muy usado para gestionar traducciones en aplicaciones Laravel:

  • laravel-lang/lang
  • laravel-lang/http-statuses
  • laravel-lang/attributes
  • laravel-lang/actions

Las etiquetas maliciosas se publicaron en sucesión rápida, muchas con segundos de diferencia, lo que apunta a que los atacantes tenían acceso a credenciales de nivel organizacional en el proyecto.

Cómo funcionaba el ataque

El método fue directo. Los atacantes añadieron un archivo src/helpers.php al campo autoload.files del composer.json de cada paquete. Esto hace que Composer ejecute ese archivo automáticamente en cada arranque de la aplicación, sin que el desarrollador tenga que invocar nada.

El archivo no resultaba obvio a simple vista. Para ocultar la dirección del servidor de control (C2), construía dinámicamente el dominio flipboxstudio[.]info usando array_map('chr', [...]), una forma de concatenar caracteres por su código ASCII que elude el análisis estático básico. Las peticiones al C2 deshabilitaban la verificación TLS, y el payload descargado se guardaba en sys_get_temp_dir()/.laravel_locale/ para ejecutarse después con exec("php ...") en Unix o mediante un script .vbs en Windows. Las comunicaciones viajaban cifradas con XOR usando la clave k9X2mP7vL4nQ8wR1.

Para no levantar sospechas ejecutándose varias veces en la misma máquina, el malware generaba un hash MD5 combinando la ruta del directorio, la arquitectura del sistema y el inodo del fichero. Solo corría una vez por máquina.

Todo lo que robaba

El payload de segunda etapa incluía 17 recolectores especializados. La lista de lo que buscaba es amplia: tokens CI/CD, claves SSH y archivos .env, credenciales de AWS (access keys, secret keys y session tokens), GCP, Azure, DigitalOcean, Heroku, Vercel y Netlify. También tokens de Kubernetes extraídos desde /var/run/secrets/ y variables de entorno de proceso desde /proc/[pid]/environ.

En el apartado de herramientas de desarrollo: archivos kubeconfig, tokens de HashiCorp Vault, configuraciones de Helm y Docker, archivos .git-credentials, .npmrc, .pypirc y configuraciones del CLI de GitHub. Los historiales de shell de bash, zsh, psql, mysql, python y node también entraban en el saco.

Para datos locales del sistema: contraseñas de 17 navegadores basados en Chromium, Firefox, KeePass, 1Password y Bitwarden. Billeteras de criptomonedas (Bitcoin, Ethereum, Monero) y extensiones como MetaMask. Tokens de Slack, Discord y Telegram.

Y para las máquinas con Chrome actualizado: un binario de Chromium embebido en base64 que servía para saltarse las protecciones introducidas en Chrome v127.

Una vez enviada toda esa información al endpoint flipboxstudio[.]info/exfil cifrada con AES-256, el malware se eliminaba del disco para dejar el menor rastro forense posible.

Cómo se detectó

Aikido lo marcó como problema crítico con puntuación 100/100 en su plataforma de análisis de dependencias. Socket y StepSecurity publicaron análisis técnicos que explican paso a paso el funcionamiento del payload, incluyendo el mecanismo de ofuscación del C2 y la lógica anti-duplicación. Okta, por su parte, publicó una guía sobre cómo defenderse de los ataques de TeamPCP en cadenas de suministro de software.

Qué hacer para reducir el riesgo

PHP y Laravel funcionaban perfectamente. El problema era más sencillo: los atacantes aprovecharon la confianza depositada en etiquetas Git sin verificar. Estas medidas reducen bastante la exposición:

  • Fijar dependencias con hashes. El archivo composer.lock debe estar en el repositorio y verificarse en cada despliegue.
  • Mínimo privilegio en tokens CI/CD. Un token que solo puede leer no puede exfiltrar secretos de escritura.
  • Revisar los cambios en dependencias antes de hacer merge. Un diff en composer.json que añade una entrada en autoload.files merece atención.
  • Mantener un SBOM (Software Bill of Materials) actualizado para saber qué hay exactamente en producción.
  • Ventana de espera para actualizaciones no urgentes. Dejar pasar unos días antes de actualizar paquetes que no son críticos da tiempo a que la comunidad detecte problemas.
  • Escanear secretos y dependencias con herramientas como GitGuardian, Socket, Snyk, Aikido o StepSecurity Harden-Runner.

Fuente: administraciondesistemas.com

Imagen: Pexels / Markus Spiske

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP