Web App 6 min de lectura

php2shell: como LFI, subida y filter chains se convierten en RCE en PHP

Guía defensiva sobre php2shell: cómo LFI, subida insegura, phar y PHP filter chains se vuelven RCE, CVEs reales y herramientas públicas para validar y corregir.

También en ENPTPT-BR
php2shell: como LFI, subida y filter chains se convierten en RCE en PHP

¿Buscas las CVE PHP2Shell de octubre de 2026 (CVE-2026-109618 y CVE-2026-109619)? Lee qué hacer ahora.

Resumen: "php2shell" no es una única herramienta, sino una familia de técnicas que convierten un fallo PHP común — Local/Remote File Inclusion, subida insegura, deserialización vía phar://, envenenamiento de logs y las modernas PHP filter chains — en ejecución de código (RCE) o web shell. Esta guía es defensiva: explica cómo detectar, validar con herramientas públicas y corregir cada camino, sin entregar exploits listos para usar.

Casi toda cadena de compromiso grave en aplicaciones PHP termina en el mismo lugar: el atacante logra que el intérprete ejecute su código. El punto de partida varía — un parámetro que entra en un include, un formulario de subida mal validado, una librería que abre ficheros con phar:// — pero el destino siempre es la shell. Entender estos puentes es el primer paso para cerrarlos.

Qué significa "php2shell"

El término describe la transición de una primitiva débil a RCE. Una lectura arbitraria de ficheros ya es grave por sí sola; pero la preocupación real del equipo defensivo aparece cuando esa lectura (o escritura, o inclusión) puede escalarse hasta ejecutar comandos en el servidor. Mapear estas transiciones es justo lo que hacemos en un pentest de aplicación web.

Los puentes más comunes

  • Local File Inclusion (LFI) a RCE. Un parámetro controlado por el usuario que llega a include/require permite incluir ficheros del servidor. Antes requería un fichero "envenenable" (logs, sesiones). Hoy, la técnica de PHP filter chain eliminó ese requisito.
  • Subida insegura. Validación por extensión o Content-Type, directorios de subida ejecutables o nombres predecibles permiten subir un .php y acceder directamente.
  • Deserialización vía phar://. Operaciones de fichero sobre una ruta phar:// controlada pueden disparar deserialización de metadatos y cadenas de gadgets.
  • Envenenamiento de logs/sesiones. Inyectar PHP en un recurso que luego se incluye.

PHP filter chains: por qué la LFI se volvió más peligrosa

La técnica de filter chain, publicada por Synacktiv en 2022, fue un punto de inflexión. Encadenando conversiones de charset iconv dentro de php://filter, es posible forjar bytes arbitrarios en memoria a partir de un sink que solo lee un fichero. En la práctica: una LFI antes considerada "solo lectura" pasa a permitir RCE sin necesidad de subida, sin fichero escribible y sin acceso a logs. Para el defensor, la lección es clara: no trate ninguna inclusión de ficheros como bajo riesgo. Fuente: thehacker.recipes — PHP wrappers and streams.

Técnica, CVE de ejemplo y cómo validar

Técnica CVE / ejemplo Cómo validar (entorno autorizado) Corrección
Subida insegura a web shell CVE-2024-11635 (WP File Upload, RCE, CVSS 10) Intentar enviar fichero inesperado y ver si queda en directorio servido/ejecutable Allow-list por magic bytes, directorio sin ejecución, nombres aleatorios
Subida no autenticada vía REST CVE-2025-13329 (File Uploader for WooCommerce, CVSS 9.8) Revisar endpoints REST que reciben ficheros sin capability/nonce Autenticación y autorización en el endpoint; validar tipo en servidor
Inyección en parámetro de comando (mailer) CVE-2016-10033 (PHPMailer < 5.2.18, CVSS 9.8) Confirmar versión de la dependencia (composer.lock) Actualizar la librería; validar/sanear el remitente
LFI a RCE (filter chain) Técnica Synacktiv (clase, no un único CVE) Verificar si parámetros llegan a include/require con wrappers php:///data:// Allow-list de ficheros incluibles; nunca concatenar input en include
Deserialización phar:// GHSA phar-stream-wrapper Mapear llamadas de fichero que aceptan ruta controlada stream_wrapper_unregister('phar') cuando no se use

Herramientas públicas para validar (uso defensivo)

Use estas herramientas solo en sistemas que está autorizado a probar.

synacktiv/php_filter_chain_generator

Script Python que genera cadenas de php://filter para evaluar si un sink de inclusión es explotable. En contexto defensivo, sirve para demostrar la accesibilidad de un parámetro sospechoso hasta el include y priorizar la corrección. Repositorio: https://github.com/synacktiv/php_filter_chain_generator.

PayloadsAllTheThings (categoría File Inclusion)

Colección de referencia muy reputada con la taxonomía de LFI/RFI y wrappers PHP, útil para armar casos de prueba y checklists de revisión. Repositorio: https://github.com/swisskyrepo/PayloadsAllTheThings.

projectdiscovery/nuclei

Scanner basado en plantillas YAML, con plantillas públicas para LFI, path traversal y patrones de RCE. Ejecute nuclei -u https://objetivo -tags lfi,rce para un triaje rápido y reproducible en pipeline. Repositorio: https://github.com/projectdiscovery/nuclei.

wpscanteam/wpscan

Para el ecosistema WordPress, donde aparece la mayoría de CVEs de subida/RCE en plugins. wpscan --url https://objetivo --enumerate vp lista plugins vulnerables conocidos. Repositorio: https://github.com/wpscanteam/wpscan.

sullo/nikto

Scanner de servidor web clásico, útil para hallar ficheros expuestos, directorios de subida abiertos y configuraciones por defecto. Repositorio: https://github.com/sullo/nikto.

semgrep, Psalm y PHPStan (análisis estático)

La validación más barata está en el propio código. Semgrep (https://github.com/semgrep/semgrep) detecta input que llega a include/system. Psalm (https://github.com/vimeo/psalm) y PHPStan (https://github.com/phpstan/phpstan) rastrean taint y tipos, señalando datos no confiables que alcanzan sinks peligrosos. Ejecútelos en el CI.

Qué cambió en PHP 8.x

PHP 8 redujo — pero no eliminó — algunos caminos. La deserialización automática de metadatos phar en operaciones de fichero comunes se eliminó; el RCE solo vuelve si el código llama explícitamente a Phar::getMetadata(). allow_url_include sigue en Off por defecto, dificultando la RFI remota directa. Pero filter chains, subidas inseguras y LFI local siguen siendo plenamente viables. Fuente: pentesterlab — PHAR Deserialization.

Lista de corrección

  • Nunca concatene input en include/require; use allow-list fija.
  • Valide subidas por magic bytes y sírvalas desde un directorio sin ejecución de PHP.
  • Mantenga allow_url_include=Off y elimine wrappers no usados.
  • Ejecute análisis estático en el CI y scanners en staging.
  • Actualice dependencias y vigile los CVEs de los plugins/librerías que usa.

Validar estos puentes exige método y autorización — es lo que separa un pentest de un scanner automático. Si opera APIs además del app PHP, vea también nuestra guía de pentest de API y de BOLA/IDOR.

Preguntas frecuentes

¿Es "php2shell" un malware?

No. Es un término paraguas para técnicas que escalan un fallo PHP hasta la ejecución de código. El riesgo es la clase de vulnerabilidad en su aplicación.

¿Actualizar a PHP 8 me protege?

Ayuda con phar y RFI, pero no resuelve subida insegura, LFI local ni filter chains.

¿Es suficiente un WAF?

Reduce ruido y frena payloads obvios, pero filter chains y subidas bien construidas pasan con frecuencia. Trate el WAF como capa, no como corrección.

¿Cuánto cuesta validar esto en un pentest?

Depende del tamaño de la aplicación y del número de sinks. Vea cuánto cuesta un pentest.