Ir al contenido
Todos los artículos

Subidas de archivos seguras en aplicaciones PHP y WordPress: guía práctica

Los formularios de subida son una vía común de entrada a sitios PHP. Cinco hábitos los protegen: tipos permitidos, almacenamiento seguro, sin ejecución de scripts, límites y análisis.

M Por Max · 6 min de lectura
Subidas de archivos seguras en aplicaciones PHP y WordPress: guía práctica

Un formulario de subida de archivos es una de las entradas más fáciles a un sitio web en PHP cuando está mal construido, porque un atacante que logra subir un archivo .php y luego abrirlo en el navegador puede ejecutar su propio código en su servidor. Las subidas seguras se apoyan en cinco hábitos: aceptar solo los tipos de archivo que necesita y comprobar su contenido real, renombrar los archivos y guardarlos fuera de la raíz web (o al menos donde no puedan ejecutarse scripts), bloquear la ejecución de scripts en cualquier carpeta de subidas, fijar límites de tamaño en el servidor y analizar lo que llega. Esta guía cubre cada uno para aplicaciones PHP a medida y para WordPress, en términos que un gerente de oficina puede usar al hablar con su desarrollador o proveedor de hosting.

Por qué las subidas son riesgosas

Los formularios de contacto con adjuntos, la recepción de currículums, los portales de documentos para clientes y la biblioteca de medios de WordPress aceptan archivos desde fuera. Lo que puede salir mal:

  • Web shells: un archivo PHP disfrazado de imagen (factura.pdf.php, o una imagen real con código PHP dentro) se guarda en una carpeta pública y se ejecuta.
  • Documentos maliciosos: un archivo de Office o un PDF inofensivo para el servidor pero peligroso para el empleado que lo abre.
  • Abuso de recursos: archivos enormes o numerosos que llenan el disco o la memoria.
  • Trucos con rutas: un nombre como ../../config.php que intenta escribir fuera de la carpeta de subidas.

1. Permita solo los tipos que necesita y compruebe el contenido

Decida exactamente qué formatos necesita el formulario (por ejemplo PDF, JPG y PNG) y rechace todo lo demás. Use una lista de permitidos, no una lista de bloqueados; OWASP señala que las listas de bloqueo son fáciles de eludir.

No confíe en lo que dice el navegador. El manual de PHP es claro: $_FILES['…']['type'] no se verifica del lado de PHP, porque lo controla por completo el cliente. En su lugar:

  • Compruebe la extensión contra su lista de permitidos.
  • Detecte el tipo real a partir del contenido del archivo en el servidor, por ejemplo con finfo de PHP (FILEINFO_MIME_TYPE), y asegúrese de que coincide con la extensión.
  • En el caso de las imágenes, volver a procesarlas (guardarlas de nuevo con GD o Imagick al mismo tamaño o menor) elimina la mayoría de las cargas ocultas.

OWASP añade que la verificación de la firma del archivo no debe usarse por sí sola, y por eso los siguientes pasos importan igual.

En WordPress

WordPress compara las subidas con una lista de tipos de archivo permitidos e intenta detectar el tipo real a partir del contenido (wp_check_filetype_and_ext). Conserve esa protección:

  • No defina ALLOW_UNFILTERED_UPLOADS en wp-config.php. Permite que los usuarios con la capacidad unfiltered_upload se salten la verificación de tipos.
  • Tenga cuidado con los plugins que "permiten cualquier tipo de archivo" o que habilitan la subida de SVG sin sanearlos.
  • Limite quién puede subir archivos: asigne al personal el rol más bajo que le permita hacer su trabajo y revise los plugins de formularios que aceptan adjuntos del público.

2. Renombre los archivos y guárdelos de forma segura

  • Genere usted el nombre con el que se guarda (por ejemplo un identificador aleatorio) y conserve el nombre original solo en la base de datos para mostrarlo. OWASP recomienda cambiar el nombre del archivo por uno generado por la aplicación.
  • Elimine las partes de directorio de cualquier nombre que sí use; el ejemplo del manual de PHP usa basename() para ayudar a evitar el recorrido de rutas (path traversal).
  • Use move_uploaded_file(), que solo mueve archivos realmente subidos desde la carpeta temporal de PHP.
  • Guarde los archivos fuera de la raíz web cuando pueda, como /home/site/private-uploads/, y entréguelos mediante un script que compruebe que el usuario tiene permiso para ver ese archivo. Así deberían servir los portales de clientes las facturas, contratos e identificaciones.
  • Asigne permisos restrictivos a los archivos guardados (sin permiso de ejecución).

Desarrollador revisando el código que gestiona las subidas en un portátil

3. Bloquee la ejecución de scripts en las carpetas de subidas

Algunas subidas tienen que ser públicas, como las imágenes de la biblioteca de medios de WordPress (wp-content/uploads). En esas carpetas, asegúrese de que el servidor web nunca ejecute PHP, aunque se cuele un archivo .php.

Nginx (dentro del bloque server del sitio, antes de la regla general de PHP):

location ~* ^/wp-content/uploads/.*\.(php|phar|phtml)$ {
    deny all;
}

Apache (un .htaccess en la carpeta de subidas o, mejor aún, en la configuración principal):

<FilesMatch "\.(php|phar|phtml)$">
    Require all denied
</FilesMatch>

OWASP también recomienda desactivar las configuraciones por directorio (como .htaccess) en las carpetas de subidas, para que un archivo de configuración subido no pueda cambiar estas reglas. En Apache, eso significa AllowOverride None para la ruta de subidas en la configuración principal.

Del lado de PHP-FPM, configure security.limit_extensions = .php para que FPM se niegue a ejecutar cualquier archivo que no sea .php, y ejecute cada sitio con su propio usuario del sistema para que una subida exitosa no alcance a otros sitios.

Después de aplicar la regla, pruébela: coloque un archivo .php de prueba inofensivo en la carpeta de subidas, confirme que el navegador recibe "403 Forbidden" en lugar de ejecutarlo y luego borre el archivo.

4. Fije límites de tamaño en el servidor

Los límites en el navegador o en el campo oculto MAX_FILE_SIZE de un formulario son solo una comodidad. El manual de PHP advierte que es muy fácil engañar ese ajuste desde el navegador, mientras que los límites del servidor no pueden engañarse. Configure:

  • PHP: upload_max_filesize, post_max_size (debe ser mayor) y max_file_uploads.
  • Servidor web: client_max_body_size en Nginx o LimitRequestBody en Apache.
  • Aplicación: un límite por formulario acorde a la necesidad real (un currículum no necesita 100 MB), además de un máximo para la longitud del nombre del archivo.
  • Revise $_FILES['…']['error'] y gestione los errores de tamaño con un mensaje claro.

5. Analice y maneje los archivos con seguridad

  • Analice las subidas en busca de malware antes de que alguien las abra. Las opciones incluyen ClamAV en el servidor, el análisis integrado en algunos servicios de formularios o almacenamiento, o la protección de endpoints en los equipos del personal. OWASP sugiere pasar los archivos por un antivirus o un sandbox cuando sea posible.
  • Las herramientas de Content Disarm & Reconstruct (CDR) reconstruyen archivos de Office y PDF sin contenido activo, algo útil en portales que reciben muchos documentos.
  • Sirva las descargas de forma segura: envíe Content-Disposition: attachment y el Content-Type correcto, además de X-Content-Type-Options: nosniff, para que los navegadores no intenten mostrar un archivo disfrazado como página web.
  • Exija inicio de sesión para todo lo que no deba ser público y registre quién subió qué.

Lista de verificación rápida

  • Lista de tipos permitidos, verificada por extensión y contenido real
  • Archivos renombrados en el servidor; los nombres originales nunca se usan como rutas
  • Archivos privados guardados fuera de la raíz web y servidos con control de acceso
  • Ejecución de PHP bloqueada en cada carpeta pública de subidas (probado)
  • security.limit_extensions = .php en PHP-FPM; un usuario del sistema por sitio
  • Límites de tamaño en PHP, en el servidor web y en la aplicación
  • Análisis de malware activo; descargas enviadas con encabezados seguros
  • WordPress: sin ALLOW_UNFILTERED_UPLOADS, roles revisados

Haga revisar sus formularios de subida

Si su sitio recibe currículums, documentos de clientes o fotos, una revisión breve puede confirmar que estas protecciones están activas. Core Florida IT protege sitios web, instalaciones de WordPress y servidores web para empresas de Miami-Dade y el sur de Florida, y de forma remota en todo el país. Solicite una evaluación de TI gratuita para empezar.

Fuentes

Siga leyendo

Hagamos de su TI la parte más sólida de su negocio.

Agende una evaluación de TI gratuita y sin compromiso. Le mostraremos exactamente dónde está y qué conviene resolver primero.

Llamar Evaluación gratuita