En resumen: post_max_size limita el tamaño total de una petición POST y upload_max_filesize el de cada archivo; por defecto, según el manual de PHP, son 8M y 2M. Los valores deben encajar con los límites del servidor web y de la aplicación; de lo contrario, las subidas fallan sin un mensaje claro. Hasta la actualización de PHP2Shell, php.net recomienda post_max_size = 8M sin subidas o 32M con subidas, y upload_max_filesize por debajo, fijado de modo que las aplicaciones no lo sobrescriban.
Cuando el formulario de candidaturas se queda de pronto en silencio
Tras las medidas transitorias para PHP2Shell, muchos administradores han reducido post_max_size. Pocos días después, el departamento de personal informa de que las candidaturas ya no llegan. El formulario simplemente se recarga, sin mensaje de error. La razón: la petición con tres PDF adjuntos era mayor que el nuevo límite, y PHP descartó los datos del formulario.
El ejemplo muestra el problema de fondo. Los límites de subida actúan en varios puntos a la vez, y cada punto reacciona de forma distinta cuando se supera. Quien conoce la cadena puede fijar los valores de modo que protejan sin perturbar el funcionamiento. Cómo procesa PHP internamente las subidas lo explica Cómo procesa PHP las subidas de archivos; la programación segura de las funciones de subida la describe Implementar subidas de archivos seguras en PHP.
La cadena de límites de subida
Una petición atraviesa varios límites antes de que la aplicación la vea. Los datos siguientes proceden de las documentaciones de Nginx, Apache y PHP:
| Punto | Ajuste | Valor por defecto según la doc. | Al superarlo |
|---|---|---|---|
| Nginx | client_max_body_size |
1m | error 413 al navegador |
| Apache desde 2.4.54 | LimitRequestBody |
1 GiB (hasta 2.4.53: ilimitado) | respuesta de error en lugar de procesar |
| PHP | post_max_size |
8M | $_POST y $_FILES vacíos |
| PHP | upload_max_filesize |
2M | el archivo se rechaza con un código de error |
| PHP | max_file_uploads |
20 | se ignoran los archivos adicionales |
| PHP | max_input_vars |
1000 | faltan los campos de formulario adicionales |
De aquí resulta una regla sencilla: upload_max_filesize menor que post_max_size, y post_max_size menor que el límite del servidor web. El manual de PHP recomienda además que memory_limit sea, en general, mayor que post_max_size. Durante la medida transitoria de PHP2Shell con memory_limit=-1, esta función la asume el límite mediante contenedor o cgroup; más información en Fijar bien memory_limit.
post_max_size tras PHP2Shell: lo que recomienda php.net
En el aviso de seguridad del 21/10/2026, php.net indica para los servidores sin actualizar unos límites bajos de petición como una de las medidas transitorias. Reducen el riesgo de vías de ataque concretas, pero expresamente no son una protección completa:
- Sin subida de archivos:
post_max_size = 8M. - Con subida de archivos:
post_max_size = 32M. - En ambos casos: mantener
upload_max_filesizepor debajo depost_max_size. - Considerar además: límites en el servidor web o proxy para el tamaño decodificado de la petición, el número de campos de entrada, el número de partes multipart, el número de líneas de cabecera y la profundidad de anidamiento. Según php.net, estos límites deben abarcar también las peticiones sin un dato
Content-Lengthutilizable.
Los valores deben ir donde las aplicaciones no puedan sobrescribirlos. Como, según el manual, post_max_size y upload_max_filesize pueden cambiarse a nivel de directorio, un .user.ini o, con mod_php, un .htaccess podrían volver a subirlos:
; Pool de FPM del sitio web, con subidas (transitorio hasta la actualización)
php_admin_value[post_max_size] = 32M
php_admin_value[upload_max_filesize] = 24M
php_admin_value[max_file_uploads] = 5
En el servidor web, ajuste el límite justo por encima, para que las peticiones demasiado grandes ni siquiera lleguen a PHP:
# Nginx, en el bloque server o location
client_max_body_size 32m;
# Apache, en el VirtualHost: 32 MiB en bytes
LimitRequestBody 33554432
Después, recargue todos los workers de PHP y el servidor web. El resumen de todas las medidas transitorias figura en Medidas inmediatas si todavía no puede parchear. Si las peticiones de subida pueden además filtrarse en el proxy, y cómo, lo trata Filtrar las peticiones de subida en el borde.
Tras cada cambio, pruebe los formularios con las peticiones legítimas más grandes: candidaturas con varios adjuntos, importaciones de productos, galerías de imágenes. Un valor demasiado ajustado paraliza procesos de negocio sin que nadie vea un mensaje de error.
Determinar el valor adecuado para su sitio web
En lugar de valores generales, merece la pena hacer un breve inventario. Haga una lista de todos los formularios con subidas y anote el archivo legítimo más grande y el mayor número de archivos simultáneos. De ahí resulta la necesidad: upload_max_filesize cubre el archivo individual más grande y post_max_size la suma de todos los archivos de una petición más algo de reserva para los campos del formulario.
Si la necesidad supera los 32M, no encaja con la recomendación transitoria de php.net. Entonces es un motivo más para adelantar la actualización. Las subidas grandes también pueden gestionarse mediante un subdominio propio con un pool propio, de modo que el resto del sitio web conserve límites estrechos.
Tras la actualización a 8.5.12, 8.4.27, 8.3.36, 8.2.35 o un backport confirmado, puede volver a ajustar los valores a la necesidad real. Aun así, no deberían ser más generosos de lo necesario: todo límite que exceda la necesidad aumenta la superficie de ataque sin beneficio. Si un sitio web no necesita subidas en absoluto, file_uploads = Off es la solución más limpia.
Interpretar bien los cuadros de error
Cuando las subidas fallan, el comportamiento revela qué límite actúa. Una página con error 413 procede del servidor web. Un formulario que se recarga sin aviso o que notifica «petición no válida» apunta a datos $_POST vacíos, es decir, a post_max_size. Un aviso de la aplicación sobre un archivo concreto encaja con upload_max_filesize. Y los campos que faltan en formularios muy grandes, por ejemplo con variantes de producto, apuntan a max_input_vars. El log de errores de PHP contiene, cuando se supera post_max_size, normalmente una advertencia con el tamaño de la petición.
Para que los usuarios no queden desorientados, la aplicación debería reconocer el caso. El manual de PHP propone para ello un camino sencillo: el formulario transmite un marcador en la dirección, por ejemplo ?processed=1. Si llega ese marcador pero $_POST y $_FILES están vacíos, la petición era demasiado grande y la aplicación puede mostrar un mensaje comprensible con el tamaño permitido.
¿Cómo ayuda PHP SOS en concreto?
- Registramos todas las vías de subida de sus sitios web y averiguamos los tamaños realmente necesarios.
- Fijamos de forma coherente los límites del servidor web, de PHP y del pool, bloqueados frente a la sobrescritura, incluidos los valores transitorios de php.net.
- Probamos formularios, importaciones y subidas tras el cambio y ajustamos los valores de forma específica.
- En el marco del refuerzo de servidores, tras la actualización devolvemos los valores a la necesidad permanente.
Preguntas frecuentes
¿Cuál es la diferencia entre post_max_size y upload_max_filesize?
upload_max_filesize limita el tamaño de un único archivo subido. post_max_size limita el total de datos de una petición POST, es decir, todos los archivos y campos de formulario juntos. Según el manual de PHP, por eso post_max_size debe ser mayor que upload_max_filesize.
¿Qué ocurre si una petición es mayor que post_max_size?
Según el manual de PHP, $_POST y $_FILES quedan vacíos. La aplicación no recibe ningún dato del formulario y a menudo solo muestra un mensaje de error poco claro o recarga el formulario. Eso hace que este error sea difícil de reconocer.
¿Qué valores recomienda php.net por PHP2Shell?
Como medida transitoria hasta la actualización: post_max_size = 8M para aplicaciones sin subida de archivos, 32M para aplicaciones con subidas, y upload_max_filesize por debajo. Según php.net, no es una protección completa; solo la actualización a una versión corregida de PHP cierra las vulnerabilidades.
¿Puedo cambiar post_max_size con ini_set() en el código?
No. Según el manual de PHP, post_max_size solo puede cambiarse a nivel de directorio, por ejemplo en php.ini, en el pool de FPM, en .user.ini o, con mod_php, en .htaccess. Quien quiera imponer el valor lo fija con php_admin_value; entonces tampoco un .user.ini puede sobrescribirlo.