Situação atual: PHP2Shell. Duas vulnerabilidades críticas do PHP (CVSS 9,2) permitem executar código malicioso sem autenticação. Patches disponíveis desde 21/10/2026.O que fazer agora →

Funções de segurança integradas do PHP

O PHP traz blocos seguros para palavras-passe, valores aleatórios, escape, criptografia e sessões. Quem os usa de forma consistente evita os erros de aplicação mais comuns.

Atualizado em 6 min de leituraConhecimento PHP

Em resumo: O PHP traz funções prontas e testadas para as tarefas de segurança mais comuns: password_hash() para palavras-passe, random_bytes() e random_int() para tokens, htmlspecialchars() contra o cross-site scripting, consultas preparadas com PDO contra a SQL injection, hash_equals() para comparações seguras e a extensão Sodium para criptografia. Quem usa estes blocos de forma consistente evita a maior parte das vulnerabilidades de aplicação. Contra erros no próprio interpretador PHP, como no PHP2Shell, não ajudam; aí só ajuda a atualização.

Porquê funções de segurança integradas no PHP?

Escrever código de segurança por conta própria é propenso a erros. Um hash de palavras-passe feito à medida, um gerador de tokens caseiro ou um filtro improvisado para saídas HTML parecem muitas vezes corretos e não o são. As funções integradas estão documentadas, testadas e são mantidas com as atualizações do PHP.

Para quem decide, isto significa: não pergunte à sua agência ou equipa de desenvolvimento se as funções de segurança foram construídas à medida, mas se são usadas as funções padrão da linguagem. A tabela dá uma visão geral.

Tarefa Função Disponível desde Nota importante
Guardar palavras-passe password_hash(), password_verify() PHP 5.5 coluna até 255 caracteres; o bcrypt trunca aos 72 bytes
Tokens aleatórios random_bytes(), random_int() PHP 7.0 nunca rand() nem mt_rand() para segredos
Aleatoriedade orientada a objetos Random\Randomizer PHP 8.2 mesma segurança, interface mais flexível
Escapar a saída HTML htmlspecialchars() desde sempre as flags predefinidas desde o 8.1 escapam também as aspas simples
Comparação em tempo constante hash_equals() PHP 5.6 entrada do utilizador como segundo argumento
Criptografia moderna Sodium (sodium_*) PHP 7.2 em vez de cifragem própria
Segredos em stack traces #[\SensitiveParameter] PHP 8.2 o valor não aparece no trace
Verificar entradas filter_var() PHP 5.2 verifica o formato, não substitui o escape

Palavras-passe e tokens

O password_hash() gera um hash com salt, o password_verify() verifica-o. Com PASSWORD_DEFAULT, o PHP usa atualmente o bcrypt; desde o PHP 8.4, o fator de custo predefinido é, segundo o manual, 12 em vez de 10. Como o algoritmo predefinido pode mudar, o manual recomenda uma coluna de base de dados com 255 caracteres. No bcrypt, as palavras-passe são truncadas aos 72 bytes, o que há que ter em conta em frases-passe muito longas.

<?php
// Registo
$hash = password_hash($passwort, PASSWORD_DEFAULT);

// Início de sessão, incluindo a melhoria automática de hashes antigos
if (password_verify($eingabe, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
        $hash = password_hash($eingabe, PASSWORD_DEFAULT); // guardar de novo
    }
}

// Token para uma ligação de reposição de palavra-passe
$token = bin2hex(random_bytes(32));

Para comparações de segredos, por exemplo de uma assinatura, deve usar-se o hash_equals(). Uma comparação normal com === pode, segundo o manual, revelar pelo tempo de execução a partir de que posição dois valores diferem. Com mais detalhe: Guardar palavras-passe em PHP em segurança e números aleatórios e tokens seguros.

Escapar saídas e consultar a base de dados em segurança

O cross-site scripting surge quando entradas do utilizador chegam sem filtragem ao HTML. O htmlspecialchars() converte caracteres especiais em entidades HTML. Desde o PHP 8.1, as flags predefinidas são ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401; antes, as aspas simples não eram convertidas. Quem tem de suportar versões mais antigas indica as flags expressamente.

A SQL injection é impedida por consultas preparadas. Os valores são transmitidos separadamente do texto SQL e não podem alterar a consulta:

<?php
$stmt = $pdo->prepare('SELECT id, name FROM kunden WHERE email = :email');
$stmt->execute(['email' => $email]);
$kunde = $stmt->fetch();

echo htmlspecialchars($kunde['name'] ?? '', ENT_QUOTES, 'UTF-8');

Os detalhes estão em Evitar o cross-site scripting em PHP e na página sobre SQL injection.

Verificar entradas é um segundo passo, separado. O filter_var() determina se um valor tem um formato válido, por exemplo um endereço de correio eletrónico ou um número inteiro num intervalo permitido. Isso não substitui, porém, o escape na saída nem uma consulta preparada, porque também valores formalmente válidos podem conter caracteres especiais.

Manter segredos fora das mensagens de erro

Uma fuga de dados subestimada são os stack traces. Quando ocorre um erro numa função, o PHP regista a cadeia de chamadas com os argumentos. Se nela constar uma palavra-passe ou uma chave de API, vai parar ao registo. Desde o PHP 8.2, o atributo #[\SensitiveParameter] marca esses parâmetros; o seu valor aparece então no trace apenas como objeto SensitiveParameterValue.

<?php
function anmelden(string $benutzer, #[\SensitiveParameter] string $passwort): bool
{
    // ... verificação ...
    throw new RuntimeException('Datenbank nicht erreichbar');
}

Segundo uma nota do manual, o atributo só atua na implementação concreta, não no método de uma interface. Defina-o por isso onde o código realmente corre.

Sessões: definições seguras e novas predefinições

As sessões são um alvo frequente de ataques. Três definições são centrais: session.use_strict_mode=1 rejeita IDs de sessão que o servidor não gerou ele próprio; session.cookie_httponly=1 impede o acesso por JavaScript ao cookie de sessão; session.cookie_samesite=Lax dificulta o envio em conjunto em sites alheios. Segundo um RFC aprovado, são precisamente estes três valores que passam a predefinição com o PHP 8.6. Defina-os por si até lá, e também depois, de forma expressa, para que a configuração não dependa da predefinição.

session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.cookie_secure = 1

Mais sobre isto em Proteger sessões em PHP.

O que as funções integradas não fazem

O projeto PHP é claro na sua política de segurança: o PHP não é uma sandbox. Contornamentos do open_basedir ou do disable_functions, entradas maliciosas passadas ao unserialize() e argumentos não verificados passados a funções como mysqli_query() não são consideradas vulnerabilidades do PHP. Para os operadores, isto significa: estas definições são um hardening útil, mas não uma fronteira de segurança, e o unserialize() não tem nada a ver com dados alheios.

O segundo ponto diz respeito ao PHP2Shell. A CVE-2026-109618 e a CVE-2026-109619 permitem, segundo o php.net, a execução de código antes ou durante a execução da sua aplicação; no mod_php foi demonstrado um exploit antes de sequer ser executado código da aplicação. Nenhuma função no seu código consegue apanhar isso. A programação segura e a versão atual do PHP são duas obrigações distintas, e ambas têm de ser cumpridas.

Como ajuda concretamente a PHP SOS?

Na auditoria de segurança para aplicações PHP, verificamos de forma dirigida:

  • Tratamento de palavras-passe e tokens: são usados password_hash() e random_bytes(), ou há soluções caseiras?
  • Saídas e consultas: onde chegam entradas sem filtragem ao HTML, ao SQL ou a comandos de shell?
  • Configuração de sessões: estão definidos strict mode, HttpOnly, SameSite e Secure, e não podem ser sobrepostos?
  • Tempo de execução: corre uma versão suportada do PHP com as correções de 21/10/2026?

Perguntas frequentes

Como se guardam corretamente palavras-passe em PHP?

Com password_hash() e PASSWORD_DEFAULT; a verificação faz-se com password_verify(). Segundo o manual, a coluna da base de dados deve comportar até 255 caracteres, porque o algoritmo predefinido pode mudar no futuro.

O rand() é adequado para tokens?

Não. Para tokens, chaves e ligações de palavras-passe devem usar-se random_bytes() ou random_int(). Segundo o manual, devolvem valores aleatórios criptograficamente seguros.

Desde quando o Sodium está incluído no PHP?

A extensão Sodium, para criptografia moderna, faz parte do PHP desde o PHP 7.2.0. Nas versões mais antigas só podia ser instalada posteriormente através do PECL.

Estas funções protegem do PHP2Shell?

Não. Protegem de erros na sua aplicação. O PHP2Shell está no próprio interpretador e só se fecha com uma atualização do PHP, seguida do reinício de todos os processos PHP.

As predefinições de sessão mudam no PHP 8.6?

Sim. Segundo um RFC aprovado, o session.use_strict_mode e o session.cookie_httponly passam a estar ativados por predefinição e o session.cookie_samesite passa a Lax. Deve, ainda assim, definir expressamente as configurações existentes.

Fontes

Contacto imediato

Cada hora conta. Escreva-nos agora.

Descreva brevemente o sistema, a versão do PHP e o que observou. Entramos em contacto consigo, esclarecemos a situação e trabalhamos remotamente até o incidente estar concluído e documentado.

Ajuda imediata