Situación actual: PHP2Shell. Dos vulnerabilidades críticas de PHP (CVSS 9.2) permiten ejecutar código malicioso sin autenticación. Parches desde el 21/10/2026.Qué hacer ahora →

Sesiones y cookies en PHP

Las sesiones convierten el HTTP sin estado en un inicio de sesión que se mantiene entre varias páginas. Cómo lo resuelve PHP por dentro, qué valores por defecto rigen y qué tiene que ver session.upload_progress con PHP2Shell.

Actualizado 5 min de lecturaConocimiento de PHP

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:

  1. El navegador envía la cookie con el nombre de la sesión, por defecto PHPSESSID.
  2. session_start() lee el ID y se lo pasa al manejador de almacenamiento, por defecto files.
  3. El manejador carga los datos guardados, PHP los convierte de nuevo con el serialize_handler y rellena $_SESSION.
  4. El script lee y modifica $_SESSION como un array normal.
  5. 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.

Fuentes

Contacto inmediato

Cada hora cuenta. Escríbanos ahora.

Describa brevemente el sistema, la versión de PHP y lo que ha observado. Nos pondremos en contacto, aclararemos la situación y trabajaremos en remoto hasta que el incidente quede cerrado y documentado.

Ayuda inmediata