# Sessões e cookies em PHP

> Sessões e cookies em PHP: ID de sessão, armazenamento, valores por defeito do php.ini, progresso de upload e a medida transitória do PHP2Shell.

Fonte: https://phpsos.de/pt/php/sessions-und-cookies/  
Atualizado em: 25/10/2026  
Prestador: PHP SOS, Assistência de emergência PHP e segurança de servidores. Ajuda imediata por WhatsApp: https://wa.me/491736494914?text=Ol%C3%A1%2C%20PHP%20SOS%2C%20precisamos%20de%20ajuda%20com%20o%20nosso%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**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:

1. O navegador envia o cookie com o nome da sessão, por defeito `PHPSESSID`.
2. O `session_start()` lê o ID e passa-o ao handler de armazenamento, por defeito `files`.
3. O handler carrega os dados guardados, o PHP reconverte-os com o `serialize_handler` e preenche `$_SESSION`.
4. O script lê e altera `$_SESSION` como um array normal.
5. No fim do pedido, o PHP volta a escrever os dados. Com `session.lazy_write` (por defeito: ligado), só se tiverem sido alterados.

```php
<?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](https://phpsos.de/pt/ratgeber/session-sicherheit-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
<?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](https://phpsos.de/pt/php/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](https://phpsos.de/pt/php2shell/cve-2026-115560/), com o mesmo remédio até à próxima versão regular de correção de erros.

```ini
; 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](https://phpsos.de/pt/blog/session-upload-progress-abschalten/).

## 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](https://phpsos.de/pt/leistungen/server-haertung/).
- 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.

## Fontes

- [Manual do PHP: configuração de sessões](https://www.php.net/manual/de/session.configuration.php)
- [Manual do PHP: progresso de upload na sessão](https://www.php.net/manual/de/session.upload-progress.php)
- [Manual do PHP: setcookie](https://www.php.net/manual/en/function.setcookie.php)
- [php.net: comunicados de segurança](https://www.php.net/)
