En resumen: HTTP no recuerda nada entre dos peticiones. Una sesión de PHP lo resuelve: PHP asigna un ID de sesión aleatorio, lo envía como cookie al navegador y guarda los datos correspondientes en el servidor, por defecto como archivo. En cada petición posterior, session_start() vuelve a leer los datos a partir del ID. De la sesión de PHP forma parte también la función session.upload_progress, que php.net recomienda desactivar temporalmente en el servidor debido a PHP2Shell.
Por qué las aplicaciones web necesitan sesiones
Cada petición a un servidor web es independiente. Sin un mecanismo adicional, una tienda no sabría, al hacer clic en «Carrito», quién acaba de añadir algo, y un área de administración tendría que pedir la contraseña en cada clic. Las sesiones unen las peticiones individuales en una sesión.
Para quienes toman decisiones esto significa: tras el inicio de sesión, el ID de sesión vale tanto como el nombre de usuario y la contraseña juntos. Para los administradores significa: dónde y cómo se guardan los datos de sesión es una cuestión de seguridad, sobre todo en servidores con varios sitios web.
Qué ocurre en session_start()
El proceso es el mismo en cada petición y puede describirse en cinco pasos:
- El navegador envía la cookie con el nombre de la sesión, por defecto
PHPSESSID. session_start()lee el ID y se lo pasa al manejador de almacenamiento, por defectofiles.- El manejador carga los datos guardados, PHP los convierte de nuevo con el
serialize_handlery rellena$_SESSION. - El script lee y modifica
$_SESSIONcomo un array normal. - Al final de la petición, PHP vuelve a escribir los datos. Con
session.lazy_write(por defecto: activado), solo si han cambiado.
<?php
session_start();
$_SESSION['besuche'] = ($_SESSION['besuche'] ?? 0) + 1;
echo 'Seitenaufrufe in dieser Sitzung: ', (int) $_SESSION['besuche'];
Si aún no hay sesión, PHP genera un ID nuevo y fija la cookie. Si session.use_strict_mode está activo, PHP rechaza los ID desconocidos que da el navegador y genera uno nuevo. El manual de PHP califica este ajuste de imprescindible para la seguridad básica.
Valores por defecto que conviene conocer
Los siguientes valores rigen, según el manual de PHP, cuando no se ha configurado otra cosa. Muchas distribuciones y proveedores de hosting fijan valores propios, por lo que siempre cuenta la configuración realmente efectiva.
| Ajuste | Valor por defecto | Significado |
|---|---|---|
session.save_handler |
files |
lugar de almacenamiento de los datos, también es posible Redis o base de datos |
session.name |
PHPSESSID |
nombre de la cookie |
session.serialize_handler |
php |
formato de los datos guardados |
session.use_strict_mode |
0 |
se aceptan ID desconocidos |
session.use_only_cookies |
1 |
ningún ID de sesión en la dirección |
session.cookie_httponly |
0 |
JavaScript puede leer la cookie |
session.cookie_secure |
0 |
cookie también por HTTP sin cifrar |
session.cookie_samesite |
vacío | sin atributo SameSite |
session.gc_maxlifetime |
1440 |
segundos hasta la posible limpieza |
session.gc_probability / gc_divisor |
1 / 100 |
limpieza aproximadamente en cada centésimo inicio |
session.upload_progress.enabled |
1 |
el progreso de carga se escribe en la sesión |
Por tanto, los valores de cookie_httponly, cookie_secure y use_strict_mode no están pensados de fábrica para la seguridad. Cómo fijarlos correctamente lo describe la guía Proteger las sesiones en PHP. Los ajustes session.sid_length y session.sid_bits_per_character están marcados como obsoletos desde PHP 8.4.0.
Fijar cookies directamente
Además de la cookie de sesión, una aplicación puede fijar cookies propias. Desde PHP 7.3.0, setcookie() acepta para ello un array con opciones, incluido samesite. Desde PHP 8.5.0 existe además la opción partitioned.
<?php
setcookie('sprache', 'de', [
'expires' => time() + 60 * 60 * 24 * 30,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
Según el manual, si samesite vale None, también debe estar fijado secure; de lo contrario, el navegador bloquea la cookie. Las cookies son datos del navegador: su contenido vuelve en la siguiente petición mediante $_COOKIE y debe comprobarse como cualquier otra entrada. Más información en la página Superglobales.
session.upload_progress: indicador de progreso para cargas
Durante la carga de un archivo, PHP puede escribir el progreso en la sesión. Para ello, el formulario envía un campo oculto con el nombre indicado en session.upload_progress.name, por defecto PHP_SESSION_UPLOAD_PROGRESS. PHP guarda entonces los datos en $_SESSION bajo una clave con el prefijo upload_progress_, con datos como la hora de inicio, el tamaño total y los bytes ya procesados.
Importante para entenderlo: según el manual, PHP escribe esta información en la sesión antes de que se ejecute ningún script. Es decir, la función actúa durante el procesamiento de la petición, antes del código de la aplicación. Sus ajustes son de tipo INI_PERDIR y no pueden modificarse en tiempo de ejecución.
Sesiones y PHP2Shell: la medida provisional
Como una de las medidas provisionales frente a las vulnerabilidades de PHP2Shell, php.net indica fijar session.upload_progress.enabled=0 en el php.ini, en el pool de FPM o en la configuración del servidor y reiniciar después todos los workers, expresamente no mediante ini_set() ni .user.ini. El 23/10/2026 se añadió el aviso sobre CVE-2026-115560, con el mismo remedio hasta la próxima versión regular de corrección de errores.
; Pool de FPM del sitio web, después reiniciar todos los workers
php_admin_flag[session.upload_progress.enabled] = off
Según informes técnicos, este ajuste por sí solo no cierra las dos vulnerabilidades. La actualización a PHP 8.5.12, 8.4.27, 8.3.36 o 8.2.35 sigue siendo obligatoria. Si su aplicación utiliza siquiera el progreso de carga y cómo fijar el ajuste de forma permanente lo describe el artículo Desactivar session.upload_progress.
¿Cómo ayuda PHP SOS en concreto?
- Leemos los ajustes de sesión realmente efectivos de cada sitio web, no solo los valores de la línea de comandos.
- Fijamos las medidas provisionales de PHP2Shell por pool, reiniciamos todos los workers y comprobamos el resultado.
- Separamos los lugares de almacenamiento de sesiones y los usuarios de pool entre sitios web en el marco del refuerzo del servidor.
- Tras un incidente descartamos todas las sesiones existentes para que los ID de sesión robados no valgan nada.
Preguntas frecuentes
¿Cuál es la diferencia entre cookie y sesión?
Una cookie es un pequeño conjunto de datos que el navegador guarda y envía con cada petición. Una sesión guarda los datos propiamente dichos en el servidor; en la cookie solo hay un identificador aleatorio, el ID de sesión.
¿Cuánto dura una sesión de PHP?
La cookie de sesión vale por defecto hasta que se cierra el navegador. Los datos del servidor pueden limpiarse tras session.gc_maxlifetime, por defecto 1440 segundos sin acceso. Cuándo ocurre realmente depende de la lógica de limpieza del sistema.
¿Qué hace session.upload_progress?
La función escribe en la sesión el progreso durante la carga de un archivo para que una segunda petición pueda mostrarlo. Está activa por defecto. Debido a PHP2Shell, php.net recomienda desactivarla temporalmente en el servidor.
¿Basta con desactivar session.upload_progress con ini_set()?
No. Según el manual, el ajuste no puede modificarse en tiempo de ejecución de todos modos, y php.net menciona expresamente php.ini, el pool de FPM o la configuración del servidor como lugares correctos, no ini_set() ni .user.ini. Después hay que reiniciar todos los workers.