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.

¿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/requirepermite 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.phpy acceder directamente. - Deserialización vía
phar://. Operaciones de fichero sobre una rutaphar://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=Offy 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.