# Segurança Web: sessões e autenticação

Modelo de segurança Web, sessões, palavras-passe, XSS refletido e injeção SQL com correções.

Página: https://resumos.rgo.pt/cadeiras/fsi/seguranca-web/

A Web junta os piores ingredientes para a segurança: código de origens diferentes a correr no mesmo navegador, dados do utilizador misturados com instruções e sessões mantidas com truques. Esta página apresenta o modelo que contém essa mistura e dois ataques mínimos com as respetivas correções.

## O modelo: mesma origem, sessões e segredos

O navegador corre código de qualquer site, por isso precisa de uma regra de separação: a **política da mesma origem** (_same-origin policy_) impede que o código de um site leia os dados de outro. Sem ela, um separador malicioso lia o teu correio aberto noutro separador. É uma regra do navegador, não do servidor: protege o utilizador, e contorná-la do lado do servidor não a desliga.

O HTTP não tem memória, por isso as aplicações inventaram as **sessões**: o servidor cria um identificador aleatório, entrega-o num _cookie_ e reconhece o cliente quando ele o devolve. Quem roubar esse identificador herda a sessão (**sequestro de sessão**), daí as proteções: gerar de novo o identificador ao iniciar sessão, marcá-lo como `HttpOnly` para o JavaScript não o ler, `Secure` para só viajar em HTTPS e `SameSite` para não seguir em pedidos vindos de outros sites.

Vê a diferença que três palavras fazem no cabeçalho de resposta:

```
# antes: o identificador viaja em claro e qualquer script o lê
Set-Cookie: sessao=abc123

# depois: só em HTTPS, invisível ao JavaScript, fora de sites terceiros
Set-Cookie: sessao=abc123; HttpOnly; Secure; SameSite=Lax
```

Na **autenticação**, a regra de ouro é nunca guardar palavras-passe, nem cifradas: guarda o resultado de uma função lenta com **sal** único por utilizador (_salt_), como o bcrypt ou o Argon2. O sal derrota tabelas pré-computadas e a lentidão derrota a tentativa maciça. Verificar é repetir o cálculo e comparar; vazar a base de dados continua a ser mau, mas não entrega as palavras-passe de bandeja.

## Exemplo 1: XSS refletido e a sua correção

A página de boas-vindas da loja ecoa o nome vindo do endereço sem filtrar:

```
// VULNERÁVEL: ecoa o parâmetro tal como chegou
echo "<p>Olá, " . $_GET["nome"] . "!</p>";
```

O ataque chega num endereço partilhado com a vítima:

```
/saudar.php?nome=<script>alert(document.cookie)</script>
```

O servidor devolve o código injetado dentro da página legítima e o navegador executa-o com os privilégios do site: lê _cookies_, age em nome do utilizador, desfigura a página. É **refletido** porque o código viaja no pedido e reflete-se na resposta, sem ficar guardado.

A correção é tratar dados como texto, nunca como código, no ponto de saída:

```
// CORRIGIDO: texto é texto, mesmo que pareça código
echo "<p>Olá, " . htmlspecialchars($_GET["nome"], ENT_QUOTES, "UTF-8") . "!</p>";
```

Os carateres `<` e `>` passam a entidades inofensivas e o navegador mostra a tentativa em vez de a executar. Aplica a regra a todas as saídas, porque basta uma página esquecida.[1](https://resumos.rgo.pt/cadeiras/fsi/seguranca-web/#user-content-fn-xss-owasp)

Corre a correção com a entrada do ataque e confirma que o navegador recebe texto morto:

```php
<?php
$ataque = '<script>alert(document.cookie)</script>';
echo "<p>Olá, " . htmlspecialchars($ataque, ENT_QUOTES, "UTF-8") . "!</p>";
```

[Vídeo: Atacar sites com cross-site scripting, Computerphile](https://www.youtube.com/watch?v=L5l9lSnNMxg)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=L5l9lSnNMxg)

## Exemplo 2: injeção SQL mínima e a sua correção

A pesquisa de clientes monta a consulta por concatenação:

```
// VULNERÁVEL: interpola a entrada na consulta
$sql = "SELECT * FROM clientes WHERE nome = '" . $_POST["nome"] . "'";
```

A entrada `' OR '1'='1` transforma a consulta em `... WHERE nome = '' OR '1'='1'`, condição sempre verdadeira: devolve todos os clientes. É a mesma confusão entre dados e instruções, agora na base de dados.

A correção separa a estrutura dos dados com **consultas parametrizadas**:

```
// CORRIGIDO: a estrutura é fixa, o valor viaja à parte
$stmt = $db->prepare("SELECT * FROM clientes WHERE nome = ?");
$stmt->execute([$_POST["nome"]]);
```

O parâmetro nunca é interpretado como SQL, seja qual for o seu conteúdo. Junta a isto o privilégio mínimo na conta da base de dados, só leitura onde baste, e uma injeção que sobreviva encontra muito menos para levar.[2](https://resumos.rgo.pt/cadeiras/fsi/seguranca-web/#user-content-fn-sqli-owasp)

[Vídeo: Um ataque de injeção SQL explicado, Computerphile](https://www.youtube.com/watch?v=ciNHn38EyRc)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=ciNHn38EyRc)

O padrão comum

XSS e injeção SQL são o mesmo erro em dois palcos: concatenar entrada não validada numa linguagem que o recetor interpreta. A cura também é a mesma em espírito: valida à entrada com a [lista de permissão](https://resumos.rgo.pt/cadeiras/fsi/seguranca-web/programacao-defensiva/) e codifica ou parametriza à saída. Quando vires concatenação de SQL, HTML ou comandos do sistema com dados do utilizador, desconfia por reflexo.

## Para saber mais

*   [Guia OWASP de prevenção de XSS](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html): codificar a saída conforme o contexto.
*   [Guia OWASP de prevenção de injeção SQL](https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html): consultas parametrizadas como defesa principal.
*   [Ataques de injeção SQL na OWASP](https://owasp.org/www-community/attacks/SQL_Injection): exemplos de ataques para reconheceres o padrão.

## Notas de rodapé

1.  Guia de prevenção de XSS da OWASP, com a regra de codificar a saída conforme o contexto onde ela cai (HTML, atributo, JavaScript ou URL). [Voltar](https://resumos.rgo.pt/cadeiras/fsi/seguranca-web/#user-content-fnref-xss-owasp)
    
2.  Guia de prevenção de injeção SQL da OWASP: consultas parametrizadas como defesa principal, com conta de base de dados de privilégio mínimo. [Voltar](https://resumos.rgo.pt/cadeiras/fsi/seguranca-web/#user-content-fnref-sqli-owasp)
