ofensiva
subida de archivos insegura
unrestricted file upload
CWE-434

Subida de archivos insegura: de webshell a RCE

Subida de archivos insegura (CWE-434): bypass de validación, Content-Type spoofing, doble extensión, webshell PHP/ASPX y RCE, con controles de defensa.

Secra6 de julio de 202612 min de lectura

La subida de archivos insegura es una vulnerabilidad web en la que una aplicación acepta ficheros del usuario sin validar correctamente su tipo, su contenido o el lugar donde se almacenan, lo que permite a un atacante depositar código ejecutable en el servidor. Catalogada como CWE-434 (Unrestricted Upload of File with Dangerous Type), suele ser el primer eslabón de una cadena que termina en ejecución remota de código (RCE). El caso paradigmático consiste en colar una webshell (un script PHP, ASPX o JSP con capacidad de ejecutar comandos) burlando las comprobaciones de la aplicación y accediendo después a la URL del fichero subido para tomar el control del servidor.

Lo esencial. La subida de archivos insegura convierte un formulario aparentemente inofensivo (foto de perfil, adjunto, importación de datos) en un vector de RCE. El atacante evade validaciones de cliente y servidor mediante Content-Type spoofing, evasión de listas de extensiones, doble extensión, null byte y ficheros polyglot con magic bytes válidos. La defensa no es un único control, sino una cadena: allowlist basada en contenido, renombrado aleatorio, almacenamiento fuera del webroot, ejecución desactivada en el directorio de subida y escaneo AV/CDR.

Qué es la subida de archivos insegura (CWE-434)

Casi toda aplicación web recibe ficheros en algún punto: imágenes de avatar, documentos justificativos, hojas de cálculo para importación, currículos, firmas. El riesgo aparece cuando la aplicación confía en atributos que el cliente controla (nombre del fichero, extensión, cabecera Content-Type del multipart) en lugar de inspeccionar el contenido real, y cuando guarda el fichero en una ruta accesible y capaz de ejecutar código.

El problema no es la subida en sí, sino la combinación de dos fallos que deben darse a la vez: validación insuficiente del fichero y una ubicación de almacenamiento que permite servir o ejecutar lo subido. Si cualquiera de los dos se rompe, la subida insegura escala a RCE. Por eso se trata de un hallazgo recurrente en auditorías, en la línea de otras vulnerabilidades de aplicación web como las descritas en las 5 vulnerabilidades web más comunes de 2025.

Cadena de ataque: de la validación al RCE

Desde el punto de vista ofensivo, explotar una subida insegura es un ejercicio de evasión progresiva. Se prueba control tras control hasta encontrar el hueco que permite depositar un fichero ejecutable en una ruta servible.

Bypass de la validación en cliente

La primera barrera suele ser JavaScript: el formulario comprueba la extensión o el tipo antes de enviar. Es una defensa cosmética. Basta con desactivar JavaScript, editar el DOM, o interceptar la petición ya enviada con un proxy como Burp Suite y modificar el cuerpo del multipart después de que el navegador haya aprobado el fichero. El atributo accept de un <input type="file"> no impone nada del lado servidor. Toda validación que solo ocurra en el navegador se considera inexistente a efectos de seguridad.

Evasión de la validación en servidor

Aquí es donde se concentra el trabajo real. Las técnicas habituales:

  • Content-Type spoofing. El servidor comprueba la cabecera Content-Type del multipart, que envía el cliente. Se cambia application/x-php por image/png o image/jpeg manteniendo el payload malicioso. El servidor cree recibir una imagen.
  • Evasión de allowlist y denylist de extensiones. Contra una denylist que bloquea .php, se prueban extensiones alternativas que el intérprete sigue ejecutando: .phtml, .php5, .php7, .pht, .phar. Con variación de mayúsculas (.pHp), caracteres finales (.php., .php%20) o sufijos de flujo de datos alternativos en IIS (.php::$DATA). En el mundo ASP.NET, extensiones como .aspx, .ashx, .asmx o un .config con handlers embebidos; en Java, .jsp y .jspx.
  • Doble extensión. shell.php.jpg o shell.jpg.php explotan configuraciones de Apache con mod_mime y AddHandler mal ajustado, donde el servidor decide el handler por la primera o la última extensión reconocida.
  • Null byte. En versiones antiguas de PHP (anteriores a 5.3.4) y ciertas capas nativas, shell.php%00.jpg truncaba el nombre en el byte nulo y el fichero se guardaba como shell.php. Histórico, pero todavía visible en sistemas heredados.
  • Magic bytes y ficheros polyglot. Cuando el servidor valida por firma (por ejemplo con getimagesize()), se antepone una cabecera válida al payload: un fichero que empieza por GIF89a; seguido de <?php system($_GET['cmd']); ?> pasa la comprobación como GIF y ejecuta como PHP. También se inyecta código en metadatos EXIF de una imagen real con exiftool, generando un polyglot que es imagen legítima y código a la vez.
  • Subida de .htaccess. Si el directorio de subida lo permite, cargar un .htaccess propio que añada un handler (AddType application/x-httpd-php .xyz) convierte una extensión arbitraria en ejecutable.

De la webshell al RCE

Superada la validación, el objetivo es que el fichero acabe en una ruta servible por el servidor de aplicaciones y con la extensión que el intérprete ejecuta. Una webshell mínima en PHP como <?php system($_GET['cmd']); ?> basta para ejecutar comandos vía parámetro GET. En entornos reales se usan webshells más completas (weevely, China Chopper, o variantes ofuscadas) que ofrecen navegación de ficheros, subida y pivoting. El equivalente en IIS es una webshell ASPX, y en servidores Java una JSP.

El paso final es localizar la URL del fichero subido (a menudo predecible: /uploads/, /media/, /files/) y solicitarla. Si el servidor ejecuta el script, el atacante tiene ejecución de comandos con los privilegios del proceso web, desde donde escala a una reverse shell interactiva y a movimiento lateral. Una webshell persistente instalada por esta vía se comporta, a partir de ahí, como un backdoor: la diferencia está en el origen, no en el resultado.

Demostración desde la óptica del pentester (Burp)

En una auditoría de aplicación web el flujo es metódico y reproducible. Se apoya en un proxy de intercepción como Burp Suite, herramienta que detallamos en qué es Burp Suite y cómo se usa en pentesting web:

  1. Localizar todos los puntos de subida mediante crawling autenticado y mapear qué extensiones y tipos acepta cada uno.
  2. Subir un fichero benigno de referencia y observar la ruta de almacenamiento, el nombre resultante y si es accesible por URL.
  3. Interceptar la petición multipart con Burp Proxy y enviarla a Repeater para iterar variantes: cambiar Content-Type, alterar la extensión, aplicar doble extensión, insertar magic bytes.
  4. Automatizar la matriz de extensiones y firmas con Intruder o con listas de la Web Security Testing Guide de OWASP.
  5. Confirmar la ejecución solicitando el fichero subido y comprobando la salida del comando.

El criterio del auditor distingue entre una validación que solo comprueba extensión (débil), una que comprueba Content-Type del cliente (débil), una que valida firma pero no reprocesa el fichero (evadible con polyglot) y una que reprocesa y almacena fuera del webroot (robusta). Este análisis forma parte de cualquier pentesting de aplicaciones web serio.

Subida insegura frente a backdoor y frente a SSRF

Conviene delimitar el concepto. Una webshell subida por un formulario vulnerable es, técnicamente, un backdoor una vez instalada, pero el hallazgo de seguridad relevante no es la persistencia sino el vector: el fallo de validación que permitió depositarla. El artículo sobre backdoors trata la webshell desde el ángulo de la persistencia y la detección; aquí el foco es la explotación del canal de subida y la evasión de controles.

Tampoco debe confundirse con otros fallos de la misma familia OWASP. En SSRF el atacante abusa de peticiones salientes del servidor, y en CSRF de la confianza en las cookies del navegador. La subida insegura es un vector de inyección de código en el sistema de ficheros del servidor, con un impacto que suele ser directamente RCE.

Controles defensivos

Ningún control aislado resuelve el problema. La defensa efectiva combina validación de contenido con endurecimiento del almacenamiento, siguiendo la File Upload Cheat Sheet de OWASP.

Allowlist basada en contenido

Rechazar denylists y trabajar con allowlists estrictas de extensiones y tipos MIME esperados. Validar el contenido real, no la extensión ni el Content-Type del cliente: inspeccionar la firma con libmagic (el comando file) y, para imágenes, reprocesarlas con GD o ImageMagick, que al reencodear descartan cualquier payload embebido en metadatos. Para documentos ofimáticos y PDF, parsers dedicados y validación de estructura.

Renombrado aleatorio y almacenamiento fuera del webroot

Generar un nombre nuevo e impredecible (por ejemplo un UUID) y guardar el nombre original solo en base de datos. Almacenar los ficheros fuera del directorio raíz del servidor web, idealmente en almacenamiento de objetos (S3 o equivalente) servido mediante URLs firmadas, de modo que nunca se sirvan desde el mismo contexto que ejecuta código de la aplicación.

Desactivar la ejecución en el directorio de subida

Si los ficheros deben residir dentro del árbol web, el directorio de subida no debe ejecutar scripts. En Apache, desactivar el motor (php_admin_flag engine off) o retirar los handlers; en Nginx, no enrutar ese location hacia fastcgi_pass; en IIS, eliminar los mapeos de handler. A nivel de sistema operativo, montar el directorio sin permiso de ejecución. Añadir X-Content-Type-Options: nosniff y servir con Content-Disposition: attachment para evitar interpretación por el navegador.

Escaneo AV/CDR, límites y sandbox

Analizar cada fichero con antivirus (ClamAV u otro) y, para formatos ofimáticos y PDF, aplicar CDR (Content Disarm and Reconstruction), que neutraliza macros y contenido activo reconstruyendo el fichero. Imponer límites de tamaño y de tasa, controlar bombas de descompresión en archivos comprimidos y, en entornos sensibles, detonar el fichero en un sandbox antes de aceptarlo. Un WAF añade una capa perimetral, pero no sustituye a la validación en la aplicación.

Encaje con OWASP y CWE

La subida de archivos insegura se identifica con CWE-434. No ocupa una casilla propia en el OWASP Top 10, sino que se reparte entre A04:2021 (Insecure Design) por la ausencia de controles por diseño y A05:2021 (Security Misconfiguration) por el almacenamiento y la configuración del servidor, mientras que el resultado, la RCE, cae en categorías de inyección. La referencia metodológica concreta está en la OWASP Web Security Testing Guide, en las pruebas de subida de tipos de fichero inesperados y de ficheros maliciosos, y en la File Upload Cheat Sheet.

Casos públicos ilustran el impacto. CVE-2018-9206 afectó al ampliamente reutilizado componente jQuery File Upload (Blueimp), permitiendo subida no restringida y ejecución de código en miles de proyectos derivados. CVE-2021-22005, en VMware vCenter Server, combinó una subida arbitraria de fichero con ejecución remota sin autenticación. Y la familia CVE-2019-18935 de Telerik UI mostró cómo un canal de subida, unido a deserialización insegura, deriva en RCE explotada por actores avanzados. El patrón común es siempre el mismo: validación evadible y un destino capaz de ejecutar.

Preguntas frecuentes

¿Validar el Content-Type es suficiente para evitar una subida insegura?

No. La cabecera Content-Type del multipart la fija el cliente y se falsifica trivialmente con un proxy como Burp. La validación fiable inspecciona el contenido real del fichero (firma con libmagic, reprocesado de imágenes) y se combina con una allowlist estricta de extensiones y con almacenamiento fuera del webroot.

¿Qué es una webshell y por qué es tan peligrosa?

Es un script (PHP, ASPX, JSP) que, alojado en el servidor, permite ejecutar comandos a través de peticiones web. Una vez subida y accesible, otorga al atacante ejecución remota con los privilegios del proceso web, punto de partida para escalar privilegios, pivotar hacia la red interna y establecer persistencia como un backdoor.

¿Un fichero polyglot cómo evade la validación por magic bytes?

Un polyglot es un fichero válido para dos formatos a la vez. Anteponiendo una cabecera de imagen legítima (por ejemplo GIF89a;) al código malicioso, supera comprobaciones como getimagesize(), que solo leen los primeros bytes, mientras el intérprete ejecuta el código PHP que sigue. La defensa es reprocesar la imagen, no solo leer su firma.

¿Basta con un WAF para protegerse?

No. Un WAF filtra patrones conocidos y aporta una capa perimetral útil, pero se evade con ofuscación y variantes. La protección real reside en la aplicación: allowlist basada en contenido, renombrado, almacenamiento aislado y ejecución desactivada en el directorio de subida. El WAF complementa, no sustituye.

¿En qué se diferencia de un backdoor?

El backdoor describe el mecanismo de persistencia y acceso remoto; la subida insegura describe el vector que lo instala. Una misma webshell puede analizarse como backdoor (persistencia y detección) o como consecuencia de una subida insegura (validación evadida). La auditoría ofensiva se centra en el vector y en cerrar el fallo de validación.

Recursos relacionados

Auditar subidas de archivos con Secra

Secra evalúa los canales de subida de vuestras aplicaciones dentro de auditorías alineadas con OWASP Top 10 y la OWASP Web Security Testing Guide. Probamos la evasión de validaciones de cliente y servidor, Content-Type spoofing, listas de extensiones, doble extensión, ficheros polyglot y ejecución de webshells en un entorno controlado, y verificamos la configuración de almacenamiento y ejecución del servidor.

Entregamos hallazgos priorizados, pruebas de concepto reproducibles y recomendaciones de hardening específicas: allowlist basada en contenido, renombrado y aislamiento del almacenamiento, desactivación de ejecución en directorios de subida y escaneo AV/CDR. Si necesitáis una revisión profesional de la subida de archivos y del resto del catálogo web, escribidnos desde /es/contacto/ o consultad nuestro servicio de auditoría web y móvil.

Sobre el autor

Equipo de Secra Solutions

Ethical hackers certificados OSCP, OSEP, OSWE, CRTO, CRTL y CARTE, con más de 7 años de experiencia en ciberseguridad ofensiva. Autores de los CVE-2025-40652 y CVE-2023-3512.

Compartir artículo