Skip to main content
AltoProtected by PowerWAF

Ataque de Subida de Archivos Maliciosos

CategoríaArchivos y RutasOWASPA04:2021 – Diseño InseguroPrimera aparición2002Tiempo de lectura10 minVerificado2026-03-12
DEFINICIÓN

Un ataque de subida de archivos maliciosos explota aplicaciones web que aceptan subidas de archivos sin validar correctamente el tipo, contenido, tamaño o nombre del archivo. Al subir un archivo manipulado — una web shell disfrazada de imagen, un archivo políglota que es simultáneamente JPEG y PHP válido, o un archivo HTML con JavaScript — el atacante logra ejecución remota de código, cross-site scripting, denegación de servicio o la toma completa del servidor.

Cómo Funciona Ataque de Subida de Archivos Maliciosos

La funcionalidad de subida de archivos es una característica central de las aplicaciones web modernas: avatares de perfil, archivos adjuntos de documentos, importaciones CSV, actualizaciones de firmware. Cada endpoint de subida es una oportunidad para que un atacante coloque contenido arbitrario en el servidor. El ataque tiene éxito cuando la aplicación confía en el archivo subido sin verificar que su contenido real coincida con el tipo esperado, que su nombre no contenga secuencias de path traversal, y que la ubicación de almacenamiento prevenga la ejecución. La brecha entre lo que la aplicación asume ("esto es un JPEG inofensivo") y lo que el archivo realmente es (una web shell PHP con extensión .jpg.php) es donde vive el ataque.

1

Reconocimiento: perfilar el mecanismo de subida

El atacante analiza la funcionalidad de subida: ¿qué tipos de archivo se aceptan (por extensión, tipo MIME o inspección de contenido)? ¿Dónde se almacenan los archivos subidos — en la raíz del documento (accesible directamente por URL) o fuera de ella? ¿Se preservan los nombres de archivo o se aleatorizan? ¿Hay validación solo del lado del cliente, o también del servidor? ¿El formulario de subida usa multipart/form-data? ¿Hay límites de tamaño? El atacante inspecciona las respuestas HTTP, mensajes de error y la estructura de URLs de archivos subidos exitosamente para responder estas preguntas. Herramientas como Burp Suite interceptan y reenvían solicitudes de subida con archivos modificados.

2

Construir la carga maliciosa

Basándose en el reconocimiento, el atacante crea una carga diseñada para evadir la validación específica: (1) Manipulación de extensión: shell.php.jpg, shell.php%00.jpg (byte nulo), shell.pHp (variación de mayúsculas), shell.php5/.phtml/.phar (extensiones PHP alternativas); (2) Suplantación de Content-Type: establecer la cabecera MIME como image/jpeg mientras se sube código PHP; (3) Archivos políglotas: un archivo que es simultáneamente un JPEG válido (comienza con los bytes mágicos FF D8 FF E0) y PHP válido (contiene <?php en un offset posterior) — pasa la validación de imagen pero se ejecuta como código; (4) SVG con JavaScript incrustado para XSS; (5) Metadatos EXIF manipulados que contienen código PHP que se ejecuta cuando la imagen es procesada por include().

3

Subir y localizar el archivo

El atacante sube el archivo manipulado y determina su URL de almacenamiento. Patrones comunes incluyen /uploads/filename.ext, /media/user_id/filename o /tmp/random_hash.ext. Si la aplicación aleatoriza los nombres de archivo, el atacante puede necesitar fuerza bruta del hash, explotar una vulnerabilidad de listado de directorios, o aprovechar una falla de divulgación de información separada para encontrar el archivo. En algunos casos, la respuesta de subida contiene la URL del archivo. Si los archivos se almacenan en un directorio no accesible por web, el atacante encadena la subida con una vulnerabilidad de Inclusión de Archivos Locales para activar la ejecución.

4

Activar la ejecución

El atacante accede al archivo subido mediante su URL. Si el servidor web está configurado para ejecutar PHP (u otros lenguajes del lado del servidor) en el directorio de subidas, la web shell se ejecuta inmediatamente: visitar /uploads/shell.php?cmd=whoami devuelve el nombre de usuario del servidor. Para ataques con .htaccess en Apache, el atacante sube un archivo .htaccess que agrega ejecución PHP a archivos .jpg (AddType application/x-httpd-php .jpg), luego sube una carga PHP con extensión .jpg. Para IIS, un archivo web.config puede lograr lo mismo. Los archivos SVG con JavaScript se ejecutan en el navegador cuando se visualizan, habilitando XSS almacenado.

5

Post-explotación y persistencia

Con una web shell establecida, el atacante escala: leer credenciales de bases de datos desde archivos de configuración, volcar bases de datos, pivotar a redes internas, establecer conexiones de shell reversa para acceso interactivo, desplegar backdoors más sofisticados en ubicaciones ocultas (código ofuscado en archivos PHP legítimos existentes, scripts de re-infección basados en cron) y exfiltrar datos. La web shell frecuentemente sirve como punto de apoyo inicial para despliegue de ransomware, criptominería o acceso persistente a nivel de APT.

Ejemplos Reales

2017

Brecha de Equifax vía subida de archivos en Apache Struts (CVE-2017-5638)

Aunque principalmente fue una vulnerabilidad de ejecución remota de código en el parser de subida multipart de Apache Struts, este ataque explotó el mecanismo de procesamiento de subida de archivos. Los atacantes enviaron cabeceras Content-Type manipuladas en solicitudes de subida multipart para lograr ejecución de comandos. La brecha expuso datos personales de 147 millones de personas — incluyendo números de Seguridad Social, fechas de nacimiento y direcciones — resultando en un acuerdo de $700 millones. Sigue siendo uno de los ataques más consecuentes relacionados con subida de archivos en la historia.

2020

Subida arbitraria de archivos en WordPress vía Contact Form 7 (CVE-2020-35489)

Una vulnerabilidad de subida de archivos sin restricciones en Contact Form 7, instalado en más de 5 millones de sitios WordPress, permitía a los atacantes evadir la sanitización de nombres de archivo del plugin usando caracteres especiales en el nombre del archivo subido. Los atacantes subieron web shells PHP a través de formularios de contacto, logrando ejecución remota de código en sitios vulnerables. La vulnerabilidad fue particularmente peligrosa porque Contact Form 7 es uno de los plugins de WordPress más populares, y muchos propietarios de sitios retrasaron las actualizaciones, dejando una superficie de ataque masiva.

2023

Explotación zero-day de MOVEit Transfer (CVE-2023-34362)

La banda de ransomware Clop explotó una cadena de vulnerabilidades en MOVEit Transfer de Progress Software, incluyendo el abuso del mecanismo de transferencia de archivos para desplegar web shells en servidores afectados. La campaña comprometió a más de 2,500 organizaciones e impactó a 66 millones de individuos en todo el mundo. Las víctimas incluyeron la BBC, British Airways, Shell, Ernst & Young y numerosas agencias gubernamentales de EE.UU. El ataque demostró cómo los mecanismos de manejo de archivos en software empresarial siguen siendo un vector de ataque crítico incluso en 2023.

Impacto y Evaluación de Riesgo

La subida de archivos maliciosos se clasifica como Alta porque proporciona un camino directo desde el acceso externo no autenticado hasta la ejecución de código en el servidor. El impacto inmediato depende de la carga: las web shells otorgan control interactivo completo sobre el servidor, los criptomineros consumen recursos de cómputo, el ransomware cifra datos para extorsión, y las cargas XSS (vía SVG/HTML) comprometen a los usuarios finales. El radio de explosión se extiende mucho más allá del endpoint de subida — una vez lograda la ejecución de código, el atacante hereda el acceso del proceso del servidor web a bases de datos, servicios internos, endpoints de metadatos de la nube y sistemas de archivos montados. En entornos cloud, esto frecuentemente habilita el movimiento lateral a otros servicios vía credenciales de metadatos de instancia. La vulnerabilidad es particularmente insidiosa porque la subida de archivos es una funcionalidad legítima y esperada — los usuarios y administradores no la perciben como una superficie de ataque hasta que es explotada.

Cómo Detectar Ataque de Subida de Archivos Maliciosos

Implementar detección multicapa: (1) Reglas del WAF inspeccionando solicitudes de subida en busca de extensiones de archivo peligrosas (.php, .jsp, .asp, .aspx, .phtml, .phar, .py, .cgi, .pl, .sh, .htaccess, .config, .shtml), extensiones dobles (.php.jpg) y secuencias de bytes nulos en nombres de archivo; (2) Análisis de contenido: escanear el contenido de archivos subidos en busca de firmas de scripts (<?php, <%, <%@, <script, #!/bin, eval(, system(, exec() independientemente del tipo de archivo declarado — un JPEG que contiene <?php es un ataque políglota; (3) Monitoreo de integridad de archivos en directorios de subida para detectar web shells depositados vía otros vectores de ataque; (4) Monitoreo de comportamiento: alertar cuando el proceso del servidor web genera procesos hijo inesperados (sh, cmd.exe, powershell) después de una subida de archivo, indicando ejecución de web shell; (5) Escaneo antivirus/antimalware de todos los archivos subidos antes del almacenamiento; (6) Monitorear patrones de acceso a directorios de subida — los archivos legítimos se acceden infrecuentemente comparados con las web shells que reciben solicitudes parametrizadas repetidas.

Cómo Prevenir Ataque de Subida de Archivos Maliciosos

Aplicar defensa en profundidad para cada endpoint de subida: (1) Validar el contenido del archivo, no solo la extensión o tipo MIME — usar validación de bytes mágicos, bibliotecas de reprocesamiento de imágenes (ImageMagick, GD, Sharp) que eliminan datos no-imagen, y bibliotecas dedicadas de detección de tipo de archivo (Apache Tika, python-magic, file-type para Node.js); (2) Renombrar archivos subidos con nombres aleatorios e imposibles de adivinar con una extensión impuesta por el servidor — nunca preservar el nombre de archivo original; (3) Almacenar subidas fuera de la raíz del documento web para que no puedan ser accedidas directamente vía URL — servirlas a través de un controlador que establezca Content-Disposition: attachment y un Content-Type seguro; (4) Configurar el servidor web para nunca ejecutar scripts en el directorio de subidas (eliminar handlers PHP/CGI, denegar ejecución de scripts en IIS); (5) Imponer límites estrictos de tamaño de archivo y limitación de tasa en endpoints de subida; (6) Usar Content Security Policy (CSP) para mitigar XSS desde archivos SVG/HTML subidos; (7) En despliegues cloud, almacenar subidas en almacenamiento de objetos (S3, GCS, Azure Blob) con ACLs privadas y servir vía URLs firmadas o CDN — esto elimina completamente el riesgo de ejecución del lado del servidor.

Ejemplos de Código

Vulnerable: Trusting client-provided extension and MIME
<?php
// VULNERABLE: Multiple validation failures
$target_dir = '/var/www/html/uploads/';
$target_file = $target_dir . basename($_FILES['file']['name']);

// FLAW 1: Trusting client-sent MIME type
$mime = $_FILES['file']['type']; // Attacker controls this!
if ($mime == 'image/jpeg' || $mime == 'image/png') {

// FLAW 2: Only checking extension (shell.php.jpg bypasses this)
$ext = pathinfo($target_file, PATHINFO_EXTENSION);
if (in_array($ext, ['jpg', 'png', 'gif'])) {

// FLAW 3: Preserving original filename (allows path traversal)
move_uploaded_file($_FILES['file']['tmp_name'], $target_file);
echo "Upload successful: /uploads/" . basename($target_file);
}
}

// Attacker uploads: shell.php with Content-Type: image/jpeg
// Or: shell.php.jpg on misconfigured Apache with AddHandler php-script .php
// Or: ../../../var/www/html/shell.php as the filename
?>
Secure: Content validation, re-processing, and isolated storage
<?php
class SecureUploader {
private string $storageDir; // OUTSIDE document root
private array $allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
private int $maxSize = 5 * 1024 * 1024; // 5 MB

public function __construct(string $storageDir) {
$this->storageDir = rtrim($storageDir, '/');
}

public function upload(array $file): array {
// 1. Check for upload errors
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new RuntimeException('Upload failed');
}

// 2. Enforce file size limit
if ($file['size'] > $this->maxSize) {
throw new RuntimeException('File too large');
}

// 3. Detect real MIME type from file content (NOT client header)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$realMime = $finfo->file($file['tmp_name']);
if (!in_array($realMime, $this->allowedTypes, true)) {
throw new RuntimeException('Invalid file type: ' . $realMime);
}

// 4. Re-process image to strip any embedded code
$image = @imagecreatefromstring(file_get_contents($file['tmp_name']));
if ($image === false) {
throw new RuntimeException('Invalid image data');
}

// 5. Generate random filename with server-enforced extension
$ext = match($realMime) {
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/gif' => 'gif',
};
$newName = bin2hex(random_bytes(16)) . '.' . $ext;
$destPath = $this->storageDir . '/' . $newName;

// 6. Save the re-processed image (strips any non-image data)
match($realMime) {
'image/jpeg' => imagejpeg($image, $destPath, 85),
'image/png' => imagepng($image, $destPath, 9),
'image/gif' => imagegif($image, $destPath),
};
imagedestroy($image);

return ['id' => pathinfo($newName, PATHINFO_FILENAME), 'name' => $newName];
}
}

// Serve files through a controller — never expose the storage directory
// GET /files/{id} → reads from storage dir, sets Content-Disposition: attachment
?>

Preguntas Frecuentes

No. La cabecera Content-Type en una subida multipart es establecida por el cliente y trivialmente falsificable — un atacante puede subir una web shell PHP con Content-Type: image/jpeg. La detección MIME del lado del servidor (usando bytes mágicos del archivo) es mejor pero aún insuficiente por sí sola: los archivos políglotas pueden tener bytes mágicos de imagen válidos mientras contienen código ejecutable en un offset posterior. La validación efectiva requiere inspección de contenido, reprocesamiento de archivos (re-codificar imágenes elimina código incrustado) y controles arquitectónicos (almacenar archivos fuera de la raíz del documento, deshabilitar ejecución de scripts en directorios de subida).
Un archivo políglota es simultáneamente válido en dos o más formatos de archivo. Por ejemplo, un políglota JPEG/PHP comienza con los bytes mágicos de JPEG (FF D8 FF E0) seguidos de datos del encabezado JFIF, pasa las herramientas de validación de imagen, e incluso puede mostrarse como imagen — pero también contiene código <?php en un offset específico que se ejecuta cuando el archivo es procesado por include() de PHP o accedido directamente en un servidor mal configurado. Los políglotas explotan la brecha entre la validación (que verifica el inicio del archivo) y la ejecución (que puede analizar el archivo completo). Derrotan las defensas de una sola capa y son la razón por la que la defensa en profundidad es esencial para la seguridad de subidas.
El almacenamiento de objetos en la nube como S3 o GCS es inherentemente más seguro para subidas porque estos servicios no ejecutan código del lado del servidor — un archivo PHP almacenado en S3 se sirve como un archivo estático, no se ejecuta. Sin embargo, quedan riesgos: (1) XSS vía HTML/SVG subido servido desde el mismo origen; (2) Distribución de malware si el bucket sirve contenido subido por usuarios; (3) SSRF si la URL de subida es controlada por el usuario; (4) DoS basado en costos mediante subidas de archivos grandes. Mejor práctica: usar un bucket/subdominio dedicado para subidas, establecer Content-Disposition: attachment para descargas, escanear archivos con antimalware antes o después de la subida, e imponer límites estrictos de tamaño.
Un WAF inspecciona solicitudes de subida multipart antes de que lleguen a la aplicación, bloqueando archivos con extensiones peligrosas (incluyendo variantes ofuscadas), detectando contenido de scripts dentro de los cuerpos de archivos independientemente de la extensión, e imponiendo límites de tamaño. La protección de subidas de PowerWAF escanea firmas de contenido ejecutable en más de 30 lenguajes de scripting, detecta patrones de archivos políglotas, bloquea path traversal en nombres de archivo, y previene subidas de .htaccess/.web.config que podrían reconfigurar el servidor. La protección del WAF es una capa crítica pero debe complementar — no reemplazar — la validación a nivel de aplicación y los controles arquitectónicos.

PowerWAF bloquea automáticamente Ataque de Subida de Archivos Maliciosos antes de que llegue a tu servidor.

Implementa en minutos. Sin cambios de código. Plan gratuito disponible.

Los cupos del plan gratuito son limitados · No credit card required