Aviso legal y ético — OBLIGATORIO: todo el contenido de este módulo está diseñado exclusivamente para su uso en entornos de laboratorio propios o en sistemas sobre los que tengas autorización escrita y explícita. Practicar estas técnicas contra sistemas de terceros sin autorización es un delito en España tipificado en los artículos 197 bis y 264 del Código Penal, con penas de hasta dos años de prisión. El objetivo de este módulo es defensivo: comprender el mecanismo de ataque para saber cómo prevenirlo. El laboratorio recomendado es DVWA (Damn Vulnerable Web Application) instalado en tu propia máquina virtual.
La subida de archivos es una funcionalidad presente en casi cualquier aplicación web moderna: fotos de perfil, adjuntos en foros, documentos en portales corporativos. Cuando esa funcionalidad no está correctamente restringida, un atacante puede subir un archivo PHP (o de cualquier lenguaje que ejecute el servidor) y conseguir que el servidor lo interprete como código. El resultado es una ejecución remota de código (Remote Code Execution, RCE), una de las vulnerabilidades más graves que existen: el atacante pasa de ser un visitante anónimo a tener acceso shell sobre el servidor.
Según el proyecto OWASP — Unrestricted File Upload, esta vulnerabilidad puede dar lugar a compromisos completos del servidor, incluyendo defacement, robo de datos, movimiento lateral y pivoting hacia la red interna. En el ámbito del hacking web, dominar la defensa contra este vector es fundamental para roles como pentester, desarrollador seguro o analista de seguridad que busque certificaciones como OSCP o bug bounty.
Qué aprenderás en este módulo
- Por qué una subida de archivos sin restricciones lleva directamente a RCE.
- Qué validaciones implementan habitualmente las aplicaciones y cómo fallan.
- Técnicas de bypass: extensión, doble extensión, lista negra vs. lista blanca, Content-Type/MIME, magic bytes y null byte (nota histórica).
- Relación con path traversal y LFI a nivel conceptual.
- Dónde encaja esto en OWASP Top 10:2025 (categoría A06 — Insecure Design).
- Laboratorio paso a paso en DVWA (niveles Low, Medium y High) con una webshell didáctica mínima.
- Cómo prevenir la vulnerabilidad de forma robusta y con defensa en profundidad.
Teoría: vulnerabilidades de subida de archivos sin restricción
El mecanismo básico: de subida a ejecución
Cuando un servidor web recibe un archivo subido, lo almacena en algún directorio del sistema de ficheros. Si ese directorio está accesible por URL y el servidor está configurado para ejecutar scripts (por ejemplo, PHP) en ese directorio, el servidor interpretará el archivo como código en lugar de servirlo como dato estático.
El flujo de ataque básico tiene tres pasos:
- Subir un archivo con código ejecutable (por ejemplo, un script PHP) usando el formulario de subida de la aplicación.
- Localizar la URL pública donde el servidor ha almacenado el archivo.
- Solicitar esa URL desde el navegador: el servidor ejecuta el script y devuelve el resultado.
Para que este ataque funcione deben cumplirse dos condiciones simultáneamente: que la aplicación permita subir el archivo (sin filtrar su contenido o extensión correctamente) y que el servidor esté configurado para ejecutar scripts en la ruta de subida. Las defensas se centran en romper una o ambas condiciones.
Validaciones habituales y sus bypass
1. Validación por extensión — lista negra
La aproximación más común y más frágil: el servidor rechaza extensiones «peligrosas» como .php, .jsp o .asp. El problema es que la lista negra nunca está completa. Según qué extensiones tenga asociadas al intérprete la configuración de Apache o de PHP-FPM, PHP puede ejecutarse también con .php3, .php4, .php5, .php7, .phtml, .pht, .phar o .shtml. A esto se suma la variación de mayúsculas/minúsculas (.pHp, .PHP), que elude listas negras que comparan sin normalizar a minúsculas.
Ejemplo de bypass: si la aplicación bloquea .php pero no .phtml, subir el archivo como shell.phtml puede ser suficiente para conseguir ejecución en servidores Apache que mantengan ese manejador activo. Cuáles de estas extensiones se ejecutan depende siempre de la configuración concreta del servidor, no son universales.
2. Doble extensión
Algunos servidores interpretan el tipo de archivo basándose en la última extensión, otros en la primera. Una validación que solo mire que el nombre termina en .jpg puede ser engañada con un archivo llamado shell.php.jpg. Si el servidor Apache tiene una directiva AddHandler application/x-httpd-php .php, puede ejecutar cualquier archivo que contenga .php en cualquier parte del nombre, incluyendo shell.php.jpg.
3. Manipulación de Content-Type / MIME
Muchas aplicaciones comprueban la cabecera HTTP Content-Type del request para verificar que el archivo es, por ejemplo, una imagen (image/jpeg). Esta cabecera la envía el cliente (navegador o herramienta como Burp Suite) y puede modificarse libremente sin tocar el contenido del archivo. Un atacante intercepta la petición con un proxy, cambia Content-Type: application/x-php por Content-Type: image/jpeg y la validación pasa aunque el contenido sea código PHP.
4. Magic bytes / firma de archivo
Una validación más robusta es leer los primeros bytes del archivo y comprobar que coinciden con la firma (magic bytes) del formato esperado. Los archivos JPEG, por ejemplo, comienzan con los bytes hexadecimales FF D8 FF. Un atacante puede anteponer esos bytes a un script PHP, creando un archivo que pasa la comprobación de firma; como PHP solo interpreta lo que hay entre las etiquetas <?php ... ?> e ignora el resto del contenido como texto plano, los bytes de firma previos no impiden la ejecución. Representado en notación hexadecimal, el contenido del archivo sería:
xFFxD8xFF <?php system($_GET['cmd']); ?>
En la práctica, la forma más fiable y realista de construir este payload es insertar el código en un campo de metadatos de una imagen JPEG real (por ejemplo, con exiftool), de modo que el archivo siga siendo una imagen válida byte a byte. Dependiendo de la configuración del servidor, el intérprete PHP encuentra la etiqueta de apertura <?php dentro del archivo y ejecuta el código a partir de ahí. Esta técnica origina los llamados archivos políglotas: archivos válidos simultáneamente en dos formatos (por ejemplo, una imagen JPEG legítima que a la vez contiene código PHP ejecutable). Importante: que un servidor ejecute como PHP un archivo con extensión de imagen depende de una mala configuración del manejador o de encadenarlo con una inclusión de archivo (LFI); por sí sola, la firma manipulada no fuerza la ejecución.
5. Null byte — nota histórica
En versiones antiguas de PHP (anteriores a 5.3.4, parcheado en diciembre de 2010), una cadena con un byte nulo (%00) en el nombre de archivo se truncaba en ese punto al pasar a las funciones de sistema de ficheros, escritas en C. Subir un archivo llamado shell.php%00.jpg hacía que la validación de la aplicación viera la extensión .jpg mientras que en disco quedaba como shell.php (extensión ejecutable real). En PHP actual (8.x) esto ya no funciona: las funciones rechazan rutas con bytes nulos. Inclúyelo solo como nota histórica; sigue siendo relevante en retos CTF, sistemas legacy sin actualizar y, conceptualmente, en otros lenguajes o capas donde aún existan discrepancias de parseo entre la validación y el sistema de ficheros.
6. Subida de .htaccess
En servidores Apache, si el directorio de subidas permite la subida de archivos .htaccess, un atacante puede subir uno que instrumente al servidor a tratar ciertos tipos de archivo como PHP. Por ejemplo, una directiva AddType application/x-httpd-php .png haría que cualquier archivo .png en ese directorio se ejecute como PHP. Esto convierte cualquier imagen subida posteriormente en un vector de ejecución.
Relación con Path Traversal y LFI
La subida de archivos no siempre conduce a RCE de forma directa. Combinada con Path Traversal (manipulación de rutas con secuencias ../ para saltar fuera del directorio de subida y escribir en rutas arbitrarias del sistema), un atacante puede depositar el archivo en un directorio con permisos de ejecución que de otro modo sería inaccesible. Por otro lado, si la aplicación tiene una vulnerabilidad de LFI (Local File Inclusion), incluso un archivo subido en un directorio sin permisos de ejecución puede ser «incluido» como código PHP por otra función vulnerable de la misma aplicación. Estos encadenamientos aumentan drásticamente la superficie de ataque.
Dónde cae en OWASP Top 10
En la edición vigente OWASP Top 10:2025, el CWE-434 (Unrestricted Upload of File with Dangerous Type) está catalogado oficialmente dentro de A06:2025 — Insecure Design, donde figura como una de las debilidades notables de la categoría. El razonamiento de OWASP es que aceptar archivos ejecutables sin contemplar la amenaza desde el diseño es un fallo de diseño, no únicamente de filtrado: la arquitectura debería impedir desde el principio que un archivo subido pueda ejecutarse.
Conviene desambiguar respecto a ediciones anteriores: en OWASP Top 10:2021 el CWE-434 se asociaba a A04:2021 — Insecure Design; en la edición 2025 la categoría de diseño inseguro se renumeró a A06. La subida de archivos sin restricción no pertenece a la categoría de Injection (A05:2025). Aunque el resultado final sea ejecución de código, OWASP la clasifica por su causa raíz de diseño, no por el efecto.
En el contexto de bug bounty, una subida de archivos que lleva a RCE suele catalogarse como crítica (típicamente CVSS 9.0–10.0 según el alcance del compromiso) y es de las vulnerabilidades mejor remuneradas. Para la certificación OSCP, encadenar subida de archivos con acceso shell es una técnica habitual en pruebas de aplicaciones web.
Laboratorio: práctica paso a paso en DVWA
Recordatorio — solo en laboratorio propio: los pasos siguientes se realizan EXCLUSIVAMENTE sobre una instalación de DVWA en tu propia máquina virtual (Docker, VirtualBox, etc.). Nunca contra sistemas de terceros. El comportamiento descrito es el de una aplicación diseñada a propósito para ser vulnerable con fines educativos.
DVWA (Damn Vulnerable Web Application) es la referencia para practicar estas técnicas en un entorno seguro y controlado. Usa la instancia que montaste en el Módulo 1 con el método oficial (docker compose up -d del repositorio digininja/DVWA, que incluye DVWA + base de datos), accesible en http://localhost:4280. Tras iniciar sesión y pulsar «Create / Reset Database», navega a la sección File Upload. Nunca expongas DVWA a Internet: es vulnerable a propósito.
Nivel Low — sin validación
En el nivel Low, DVWA no aplica ninguna restricción. El objetivo es subir una webshell mínima y didáctica que ejecute un comando inofensivo para demostrar que el servidor interpreta el archivo. La webshell de ejemplo que usaremos en este módulo es intencionalmente mínima y solo ejecuta el comando whoami para mostrar el usuario del servidor:
<?php echo shell_exec('whoami'); ?>
Guarda ese contenido como test_didactico.php. En DVWA nivel Low:
- Haz clic en «Choose File», selecciona
test_didactico.phpy pulsa «Upload». - DVWA muestra el mensaje de éxito con la ruta relativa: ../../hackable/uploads/test_didactico.php successfully uploaded!
- Construye la URL completa según tu despliegue. Con la imagen oficial en contenedor (puerto 4280) sería
http://localhost:4280/hackable/uploads/test_didactico.php; en una instalación clásica bajo/dvwa,http://localhost/dvwa/hackable/uploads/test_didactico.php. - Abre esa URL en el navegador. Verás el nombre de usuario del proceso del servidor web (típicamente
www-dataen Linux).
Esto demuestra que el servidor ejecutó el PHP. En un escenario real, un atacante usaría esto para escalar privilegios, leer archivos del sistema o establecer una reverse shell. En el laboratorio, el comando whoami es suficiente para confirmar la ejecución.
Nivel Medium — bypass de Content-Type
En el nivel Medium, DVWA comprueba que el Content-Type del archivo subido sea image/jpeg o image/png. Esta validación se puede eludir interceptando la petición HTTP con Burp Suite:
- Activa el proxy de Burp Suite y configura el navegador para usarlo.
- Intenta subir el mismo
test_didactico.php. Burp intercepta la petición antes de que llegue al servidor. - En la petición interceptada, localiza la cabecera
Content-Type: application/x-php(o similar) dentro del cuerpo multipart correspondiente al archivo. - Cámbiala a
Content-Type: image/jpeg. - Reenvía la petición. DVWA acepta el archivo porque la validación solo comprueba esa cabecera, que ya has modificado.
- Accede a la URL del archivo subido como en el nivel Low.
Esto ilustra por qué el Content-Type del cliente nunca puede considerarse fuente de verdad para validación de seguridad.
Nivel High — encadenamiento con inclusión de archivo
En el nivel High, DVWA valida tanto la extensión como que los primeros bytes del archivo correspondan a una imagen real. Para superarlo, DVWA High propone una técnica de encadenamiento:
- Parte de una imagen JPEG real e inserta el código PHP en un campo de metadatos, de modo que el archivo siga siendo una imagen válida y conserve su firma
FF D8 FF. En el laboratorio DVWA esto se hace conexiftool, por ejemplo:exiftool -Comment='<?php system($_GET["cmd"]); ?>' imagen.jpg. Renombra el resultado con doble extensiónimagen.php.jpg(o.jpga secas para el encadenamiento con LFI). - DVWA High acepta el archivo porque la extensión final es
.jpgy los magic bytes parecen correctos. - Sin embargo, como la extensión es
.jpg, Apache no lo ejecutará directamente. DVWA High incluye una vulnerabilidad adicional de inclusión de archivo (LFI) en otra sección para que puedas encadenar ambas. - Usando la vulnerabilidad LFI de DVWA (sección «File Inclusion»), incluyes el archivo subido con su ruta relativa, lo que fuerza al intérprete PHP a procesarlo.
Este nivel enseña el concepto clave de encadenamiento de vulnerabilidades: ninguna técnica aislada es suficiente cuando existen múltiples vectores que combinados amplifican el impacto.
Recuerda: DVWA es una aplicación diseñada intencionalmente para ser vulnerable. Todo lo que acabas de hacer en estos pasos es el comportamiento esperado y documentado de esa aplicación de laboratorio.
Cómo prevenirlo — defensa en profundidad
La OWASP File Upload Cheat Sheet subraya que no existe una solución única: la defensa robusta requiere múltiples capas independientes. Si una falla, las demás siguen conteniendo el ataque.
1. Lista blanca de extensiones permitidas (no lista negra)
Define explícitamente qué extensiones están permitidas según la necesidad del negocio. Si la aplicación solo necesita imágenes, permite únicamente .jpg, .jpeg, .png y .webp. Rechaza cualquier otra cosa, incluidas variantes poco conocidas. Una lista negra siempre puede tener huecos; una lista blanca solo permite lo estrictamente necesario.
// Ejemplo conceptual PHP (lista blanca)
$allowed = ['jpg', 'jpeg', 'png', 'webp'];
$ext = strtolower(pathinfo($_FILES['upload']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
die('Tipo de archivo no permitido.');
}
2. Validar el tipo MIME real (no el Content-Type del cliente)
Usa la extensión fileinfo de PHP (función finfo_file()) o equivalente para leer los magic bytes del archivo almacenado temporalmente en el servidor y determinar su tipo real, independientemente de lo que el cliente declare. El Content-Type de la cabecera HTTP es controlado por el atacante y no debe usarse como validación de seguridad.
// Validación de tipo real con finfo
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['upload']['tmp_name']);
$allowed_mimes = ['image/jpeg', 'image/png', 'image/webp'];
if (!in_array($mime, $allowed_mimes)) {
die('El contenido del archivo no corresponde al tipo permitido.');
}
Ten presente la limitación: la validación de tipo real reduce el riesgo, pero no es infalible por sí sola. La propia OWASP File Upload Cheat Sheet advierte de que la comprobación de firma «se elude con facilidad» mediante archivos políglotas. Además, formatos como SVG son XML que finfo puede aceptar como image/svg+xml y, sin embargo, pueden contener JavaScript (XSS almacenado). Por eso esta capa debe combinarse siempre con las demás (lista blanca, renombrado, almacenamiento sin ejecución y cabeceras de respuesta seguras).
3. Renombrar el archivo con un nombre generado por el servidor
Nunca uses el nombre original del archivo proporcionado por el usuario para almacenarlo en el sistema. Genera un nombre aleatorio (UUID, hash, timestamp con entropía) y aplica la extensión permitida. Esto elimina los ataques por doble extensión y por manipulación del nombre.
// Renombrado seguro
$safe_name = bin2hex(random_bytes(16)) . '.jpg';
move_uploaded_file($_FILES['upload']['tmp_name'], '/uploads/' . $safe_name);
4. Almacenar los archivos fuera del webroot o sin permisos de ejecución
Este es uno de los controles más efectivos: si los archivos subidos se almacenan en un directorio que el servidor web no puede alcanzar directamente por URL (fuera del webroot), el atacante no puede solicitar la URL del archivo para activar la ejecución. Si deben ser accesibles públicamente, sírvelos a través de un script PHP que los lea como datos binarios (readfile()) y los envíe con la cabecera Content-Type apropiada, nunca dejando que el servidor los ejecute directamente.
Alternativa complementaria en servidores Apache. Atención a un matiz importante en 2026: la directiva php_flag engine off solo surte efecto cuando PHP corre como módulo de Apache (mod_php); con la configuración hoy más habitual, PHP-FPM vía FastCGI/proxy, esa directiva se ignora. Por eso es más fiable desasociar el manejador para todo el directorio (ver punto 5). En Nginx, asegúrate de que ningún bloque location de la carpeta de subidas pase los archivos a PHP-FPM (sin fastcgi_pass ni SetHandler hacia el socket de PHP).
5. Deshabilitar la ejecución de scripts en el directorio de subidas
Mediante configuración del servidor web, marca el directorio de uploads como no-ejecutable para todos los lenguajes de scripting del servidor. En Apache, lo robusto es retirar el manejador y desactivar CGI para ese directorio (esto funciona tanto con mod_php como con PHP-FPM, a diferencia de php_flag):
<Directory /var/www/html/uploads>
# Quitar cualquier manejador de scripting asociado
RemoveHandler .php .phtml .php3 .php4 .php5 .php7 .phar .pl .py .cgi
RemoveType .php .phtml .php3 .php4 .php5 .php7 .phar
# Forzar que todo se sirva como descarga, no como script
SetHandler none
Options -ExecCGI
# Si se usa mod_php, además:
<IfModule mod_php.c>
php_admin_flag engine off
</IfModule>
</Directory>
No uses AddHandler cgi-script .php con la intención de «neutralizar»: eso asocia el manejador CGI a esos ficheros y, con CGI habilitado, podría provocar justo su ejecución. La idea correcta es quitar manejadores, no añadir uno nuevo. En Nginx, no incluyas el directorio de uploads en ningún location ~ .php$ que enrute a PHP-FPM, o añade una regla explícita que deniegue la ejecución, por ejemplo:
location ^~ /uploads/ {
location ~ .(php|phtml|phar)$ { deny all; }
}
6. Límites de tamaño
Configura límites estrictos de tamaño de archivo tanto en la aplicación como en el servidor. Archivos excesivamente grandes pueden usarse en ataques de denegación de servicio o para ocultar payloads en streams de datos voluminosos. En PHP, las directivas relevantes son upload_max_filesize y post_max_size en php.ini.
7. Escaneo antivirus / sandbox
Para aplicaciones que requieren subir documentos de oficina, PDFs u otros formatos complejos (donde las listas blancas de extensión son menos restrictivas), integrar un motor antivirus (como ClamAV) o un servicio de análisis sandbox en el flujo de subida añade una capa de detección de contenido malicioso antes de que el archivo sea accesible.
8. Cabeceras de respuesta seguras al servir los archivos
Cuando los archivos se sirven a través de un script, fuerza cabeceras que impidan que el navegador interprete contenido inesperado. X-Content-Type-Options: nosniff evita que el navegador «adivine» (MIME sniffing) un tipo distinto del declarado, y Content-Disposition: attachment (o un Content-Type explícito y correcto) reduce el riesgo de que una imagen políglota o un SVG/HTML malicioso se ejecute en el contexto del sitio. Es la capa que mitiga el XSS almacenado vía archivos subidos.
// Al entregar un archivo subido mediante un script
header('Content-Type: image/jpeg');
header('X-Content-Type-Options: nosniff');
header('Content-Disposition: attachment; filename="' . $safe_name . '"');
readfile($ruta_fuera_del_webroot);
9. CDN y almacenamiento externo
Servir los archivos subidos desde un dominio o subdominio completamente separado del dominio de la aplicación (por ejemplo, un bucket de AWS S3 o un CDN) aísla cualquier código que pudiera ejecutarse: aunque el atacante consiga subir un script, este nunca se ejecutará en el contexto del servidor de la aplicación principal. Además, servirlos desde un origen distinto limita el alcance de ataques XSS derivados de archivos HTML o SVG maliciosos subidos.
Resumen de controles
| Control | Eficacia contra bypass | Dificultad de implementación |
|---|---|---|
| Lista blanca de extensiones | Alta (si está bien definida) | Baja |
| Validación MIME real (finfo) | Alta | Baja |
| Renombrado de archivo | Muy alta (elimina doble ext.) | Muy baja |
| Almacenamiento fuera del webroot | Muy alta | Media |
| Deshabilitar ejecución en /uploads | Muy alta | Baja |
| Límites de tamaño | Parcial (anti-DoS) | Muy baja |
| Escaneo AV / sandbox | Media (depende del motor) | Alta |
| Cabeceras seguras (nosniff / Content-Disposition) | Alta (frente a XSS por SVG/HTML) | Muy baja |
| CDN / dominio separado | Alta | Media |
Ejercicio propuesto
Una vez completado el laboratorio en DVWA, proponte los siguientes retos adicionales en el mismo entorno:
- DVWA nivel Medium con Burp Suite: instala Burp Suite Community Edition, configura el proxy y repite el bypass de Content-Type capturando y modificando la petición HTTP. Observa en la pestaña «Proxy > HTTP history» todos los detalles del request multipart.
- Archivo políglota: con la herramienta
exiftool(disponible en Kali Linux), inserta un comentario PHP en los metadatos de una imagen JPEG real:exiftool -comment='<?php echo shell_exec("id"); ?>' imagen.jpg. Sube el archivo a DVWA Medium e intenta acceder a él. Reflexiona sobre qué condiciones adicionales necesitarías para que se ejecute. - Defensa activa: modifica el código fuente de DVWA (disponible en tu instancia local, en
/var/www/html/dvwa/vulnerabilities/upload/) para añadir las tres capas de defensa: lista blanca de extensiones, validación de MIME con finfo y renombrado de archivo. Verifica que tus propios ataques anteriores ya no funcionan. - Investigación: accede a la sección File Upload del Web Security Academy de PortSwigger y completa al menos dos de sus labs interactivos gratuitos sobre esta vulnerabilidad.
Errores comunes
- Confiar en el Content-Type del cliente: es el error más frecuente. Ese valor lo envía el navegador (o el atacante) y puede ser cualquier cadena arbitraria. La validación debe hacerse siempre sobre el contenido real del archivo en el servidor.
- Usar lista negra en lugar de lista blanca: siempre habrá una extensión que olvidaste bloquear. La lista blanca invierte la lógica: bloquea todo excepto lo explícitamente permitido.
- Mantener el nombre original del archivo: el nombre lo proporciona el atacante. Usarlo directamente (incluso solo para almacenamiento) expone a path traversal, inyección de caracteres especiales y doble extensión.
- Almacenar archivos en el webroot sin deshabilitar ejecución: aunque la extensión esté filtrada, un archivo
.htaccessmalicioso o una configuración inesperada del servidor pueden revertir ese control. - Aplicar solo una capa de defensa: como demuestra el nivel High de DVWA, una sola medida puede encadenarse con otra vulnerabilidad. La defensa en profundidad es la única estrategia efectiva.
- No revisar la configuración del servidor: incluso con una aplicación bien defendida a nivel de código, una directiva Apache incorrecta puede habilitar la ejecución de PHP en directorios de subida. La seguridad de la infraestructura y la del código deben auditarse juntas.
Preguntas frecuentes
¿Por qué el servidor ejecuta el archivo en lugar de servirlo como texto?
Porque el servidor web tiene configurado un manejador (handler) que asocia ciertos tipos de archivo o extensiones con un intérprete (PHP, Python, Perl…). Cuando un cliente solicita un archivo con esa extensión en un directorio ejecutable, el servidor pasa el archivo al intérprete en lugar de leerlo y enviarlo directamente. Deshabilitar esa asociación en el directorio de subidas (o almacenar los archivos fuera del webroot) es el control más directo.
¿Es posible explotar esta vulnerabilidad si el servidor es Nginx en lugar de Apache?
Sí, aunque los detalles varían. En Nginx, la ejecución de PHP se delega a PHP-FPM mediante fastcgi. Si el bloque de configuración de Nginx incluye el directorio de subidas dentro del bloque location ~ .php$, los archivos PHP subidos se ejecutarán igual que en Apache. El principio de defensa es el mismo: asegurarse de que la configuración de Nginx no pase los archivos del directorio de subidas a PHP-FPM. Además, una antigua vulnerabilidad de Nginx (CVE-2013-4547) permitía ejecución con rutas del tipo imagen.jpg/x.php en versiones sin parchear.
¿Qué diferencia hay entre una webshell y una reverse shell?
Una webshell es un script del lado del servidor que expone una interfaz para ejecutar comandos a través del protocolo HTTP (el atacante envía comandos vía parámetros GET/POST y recibe la salida en la respuesta). Requiere que el atacante tenga acceso HTTP al servidor. Una reverse shell es una conexión TCP iniciada desde el servidor comprometido hacia la máquina del atacante, lo que le permite obtener una sesión interactiva en la línea de comandos. La reverse shell suele ser el siguiente paso después de conseguir ejecución mediante una webshell: el atacante usa la webshell para ejecutar el comando que establece la reverse shell. En este módulo, la webshell didáctica solo ejecuta whoami como demostración conceptual, sin llegar a reverse shell.
¿Cómo sé si mi aplicación web actual es vulnerable?
Puedes realizar una auditoría básica revisando: (a) si existen formularios de subida de archivos, (b) si el directorio de destino está dentro del webroot y accesible por URL, (c) si el servidor web tiene permisos de ejecución en ese directorio, y (d) si el código de validación aplica lista blanca, validación de contenido real y renombrado. Herramientas como Burp Suite (modo activo o pasivo) pueden ayudar a identificar endpoints de subida durante una auditoría autorizada. Para obtener una formación más completa sobre auditorías y certificaciones, consulta nuestra guía de cursos y certificaciones de ciberseguridad.
Recordatorio ético y legal final
Las técnicas explicadas en este módulo — bypass de validación de subida, uso de webshells, intercepción de tráfico HTTP — son herramientas de análisis defensivo, no ofensivo. Su aplicación contra sistemas que no son tuyos o para los que no tienes autorización escrita constituye un delito en España bajo los artículos 197 bis (acceso no autorizado a sistemas informáticos) y 264 (daños informáticos) del Código Penal, con penas de prisión de hasta dos años o más según la gravedad. Practica siempre en entornos controlados como DVWA, PortSwigger Web Security Academy o plataformas de CTF. Si quieres canalizar estos conocimientos de forma profesional y legal, explora los programas de bug bounty (HackerOne, Bugcrowd) o las vías de certificación como OSCP, donde la práctica está expresamente autorizada y regulada.
