Em resumo: O HTTP não memoriza nada entre dois pedidos. Uma sessão PHP resolve isso: o PHP atribui um ID de sessão aleatório, envia-o ao navegador como cookie e guarda os dados correspondentes no servidor, por defeito como ficheiro. A cada pedido seguinte, o session_start() volta a ler os dados com base no ID. À sessão PHP pertence também a função session.upload_progress, que o php.net recomenda desativar temporariamente do lado do servidor por causa do PHP2Shell.
Porque é que as aplicações web precisam de sessões
Cada pedido a um servidor web é independente. Sem um mecanismo adicional, uma loja não saberia, ao clicar em «Carrinho», quem acabou de colocar algo nele, e uma área de administração teria de pedir a palavra-passe a cada clique. As sessões ligam pedidos isolados numa sessão de utilização.
Para quem decide, isto significa: depois do login, o ID de sessão vale tanto como o nome de utilizador e a palavra-passe juntos. Para administradores, significa: onde e como estão os dados de sessão é uma questão de segurança, sobretudo em servidores com vários sites.
O que acontece no session_start()
O procedimento é o mesmo a cada pedido e pode descrever-se em cinco passos:
- O navegador envia o cookie com o nome da sessão, por defeito
PHPSESSID. - O
session_start()lê o ID e passa-o ao handler de armazenamento, por defeitofiles. - O handler carrega os dados guardados, o PHP reconverte-os com o
serialize_handlere preenche$_SESSION. - O script lê e altera
$_SESSIONcomo um array normal. - No fim do pedido, o PHP volta a escrever os dados. Com
session.lazy_write(por defeito: ligado), só se tiverem sido alterados.
<?php
session_start();
$_SESSION['besuche'] = ($_SESSION['besuche'] ?? 0) + 1;
echo 'Seitenaufrufe in dieser Sitzung: ', (int) $_SESSION['besuche'];
Se ainda não existe sessão, o PHP gera um novo ID e define o cookie. Com session.use_strict_mode ativo, o PHP rejeita IDs desconhecidos impostos pelo navegador e gera um novo. O manual do PHP considera esta definição obrigatória para a segurança básica.
Valores por defeito que convém conhecer
Os valores seguintes valem, segundo o manual do PHP, quando nada mais está configurado. Muitas distribuições e alojadores definem valores próprios, por isso conta sempre a configuração realmente efetiva.
| Definição | Por defeito | Significado |
|---|---|---|
session.save_handler |
files |
local de armazenamento dos dados, também possível Redis ou base de dados |
session.name |
PHPSESSID |
nome do cookie |
session.serialize_handler |
php |
formato dos dados guardados |
session.use_strict_mode |
0 |
IDs desconhecidos são aceites |
session.use_only_cookies |
1 |
sem ID de sessão no endereço |
session.cookie_httponly |
0 |
o JavaScript pode ler o cookie |
session.cookie_secure |
0 |
cookie também por HTTP não cifrado |
session.cookie_samesite |
vazio | sem atributo SameSite |
session.gc_maxlifetime |
1440 |
segundos até à possível limpeza |
session.gc_probability / gc_divisor |
1 / 100 |
limpeza em cerca de um em cada cem arranques |
session.upload_progress.enabled |
1 |
o progresso do upload é escrito na sessão |
Os valores de cookie_httponly, cookie_secure e use_strict_mode não vêm, portanto, de fábrica orientados para a segurança. Como os definir corretamente descreve-o o guia Proteger sessões em PHP. As definições session.sid_length e session.sid_bits_per_character estão marcadas como obsoletas desde o PHP 8.4.0.
Definir cookies diretamente
Além do cookie de sessão, uma aplicação pode definir cookies próprios. Desde o PHP 7.3.0, o setcookie() aceita para isso um array de opções, incluindo samesite. Desde o PHP 8.5.0 existe ainda a opção partitioned.
<?php
setcookie('sprache', 'de', [
'expires' => time() + 60 * 60 * 24 * 30,
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax',
]);
Segundo o manual, com samesite igual a None também secure tem de estar definido, caso contrário o navegador bloqueia o cookie. Os cookies são dados do navegador: o seu conteúdo regressa no pedido seguinte através de $_COOKIE e tem de ser verificado como qualquer outra entrada. Mais sobre isto na página Superglobals.
session.upload_progress: indicador de progresso para uploads
O PHP pode escrever na sessão o progresso durante o upload de um ficheiro. Para isso, o formulário envia um campo oculto com o nome de session.upload_progress.name, por defeito PHP_SESSION_UPLOAD_PROGRESS. O PHP guarda então os dados em $_SESSION sob uma chave com o prefixo upload_progress_, com indicações como hora de início, tamanho total e bytes já processados.
Importante para a compreensão: segundo o manual, o PHP escreve estas informações na sessão antes de qualquer script ser executado. A função trabalha, portanto, durante o processamento do pedido, antes do código da aplicação. As suas definições são do tipo INI_PERDIR e não podem ser alteradas em tempo de execução.
Sessões e PHP2Shell: a medida transitória
Como uma das medidas transitórias contra as vulnerabilidades do PHP2Shell, o php.net indica definir session.upload_progress.enabled=0 no php.ini, no pool FPM ou na configuração do servidor e reiniciar depois todos os workers, expressamente não através de ini_set() nem de .user.ini. A 23/10/2026 foi acrescentada a indicação sobre o CVE-2026-115560, com o mesmo remédio até à próxima versão regular de correção de erros.
; Pool FPM do site, depois reiniciar todos os workers
php_admin_flag[session.upload_progress.enabled] = off
Segundo relatos especializados, esta definição por si só não fecha ambas as vulnerabilidades. A atualização para PHP 8.5.12, 8.4.27, 8.3.36 ou 8.2.35 continua a ser obrigatória. Se a sua aplicação utiliza sequer o progresso do upload e como definir a configuração de forma duradoura descreve-o o artigo Desativar o session.upload_progress.
Como ajuda concretamente a PHP SOS?
- Lemos as definições de sessão realmente efetivas por site, não apenas os valores da linha de comandos.
- Definimos as medidas transitórias do PHP2Shell por pool, reiniciamos todos os workers e verificamos o resultado.
- Separamos os locais de armazenamento de sessões e os utilizadores dos pools entre sites, no âmbito do reforço de servidores.
- Depois de um incidente, invalidamos todas as sessões existentes, para que IDs de sessão roubados deixem de valer.
Perguntas frequentes
Qual é a diferença entre cookie e sessão?
Um cookie é um pequeno registo que o navegador guarda e envia a cada pedido. Uma sessão guarda os dados propriamente ditos no servidor; no cookie consta apenas um identificador aleatório, o ID de sessão.
Quanto tempo vive uma sessão PHP?
O cookie de sessão vale, por defeito, até o navegador ser fechado. Os dados no servidor podem ser limpos após session.gc_maxlifetime, por defeito 1440 segundos sem acesso. Quando isso acontece realmente depende da lógica de limpeza do sistema.
O que faz o session.upload_progress?
A função escreve na sessão o progresso durante o upload de um ficheiro, para que um segundo pedido o possa mostrar. Está ativa por defeito. Por causa do PHP2Shell, o php.net recomenda desativá-la temporariamente do lado do servidor.
Basta desativar o session.upload_progress com ini_set()?
Não. Segundo o manual, a definição nem sequer pode ser alterada em tempo de execução, e o php.net indica expressamente o php.ini, o pool FPM ou a configuração do servidor como locais corretos, não o ini_set() nem o .user.ini. Depois, reiniciar todos os workers.