# Sesiones y cookies en PHP

> Cómo funcionan las sesiones y cookies de PHP: ID de sesión, almacenamiento, valores por defecto del php.ini, progreso de carga y la medida provisional de PHP2Shell.

Fuente: https://phpsos.de/es/php/sessions-und-cookies/  
Actualizado: 25/10/2026  
Proveedor: PHP SOS, Ayuda de emergencia para PHP y seguridad de servidores. Ayuda inmediata por WhatsApp: https://wa.me/491736494914?text=Hola%20PHP%20SOS%2C%20necesitamos%20ayuda%20con%20nuestro%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Sitio%20web%3A%20%E2%80%A6

**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
<?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](https://phpsos.de/es/ratgeber/session-sicherheit-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
<?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](https://phpsos.de/es/php/superglobals/).

## 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](https://phpsos.de/es/php2shell/cve-2026-115560/), con el mismo remedio hasta la próxima versión regular de corrección de errores.

```ini
; 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](https://phpsos.de/es/blog/session-upload-progress-abschalten/).

## ¿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](https://phpsos.de/es/leistungen/server-haertung/).
- 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

- [Manual de PHP: configuración de sesiones](https://www.php.net/manual/de/session.configuration.php)
- [Manual de PHP: progreso de carga en la sesión](https://www.php.net/manual/de/session.upload-progress.php)
- [Manual de PHP: setcookie](https://www.php.net/manual/en/function.setcookie.php)
- [php.net: avisos de seguridad](https://www.php.net/)
