Nesta aula, vamos explorar um dos aspectos mais importantes da segurança em aplicações web: a validação e sanitização de dados de entrada. Em PHP, a função filter_var é uma ferramenta poderosa que nos permite verificar e limpar dados de forma eficiente. Entender como validar e sanitizar corretamente é essencial para prevenir vulnerabilidades como injeção de SQL, XSS e outros ataques.

Ao final desta aula, você será capaz de aplicar filtros de validação e sanitização em diferentes tipos de dados, compreender a importância de nunca confiar em entradas do cliente e implementar boas práticas de segurança em seus projetos PHP.

filter_var

A função filter_var é a principal ferramenta do PHP para filtrar dados. Ela aceita dois parâmetros obrigatórios: o valor a ser filtrado e o tipo de filtro a ser aplicado. Opcionalmente, podemos passar um array de opções para configurar o comportamento do filtro. A função retorna o valor filtrado se for bem-sucedido, ou false se a validação falhar.

Existem duas categorias principais de filtros: de validação (que verificam se o dado atende a um formato esperado) e de sanitização (que removem ou modificam caracteres indesejados). Os filtros são identificados por constantes como FILTER_VALIDATE_EMAIL, FILTER_SANITIZE_STRING, etc.

$email = "usuario@exemplo.com";
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "E-mail válido.";
} else {
    echo "E-mail inválido.";
}
// Saída: E-mail válido.

Validando entradas

A validação de entradas consiste em verificar se os dados fornecidos pelo usuário estão no formato correto antes de processá-los. O PHP oferece diversos filtros de validação prontos para tipos comuns como e-mail, URL, IP, números inteiros e de ponto flutuante, entre outros.

Por exemplo, para validar uma URL, usamos FILTER_VALIDATE_URL. Para validar um número inteiro dentro de uma faixa, podemos usar FILTER_VALIDATE_INT com opções de min_range e max_range. É importante notar que a validação retorna o valor filtrado (convertido para o tipo apropriado) se for válido, ou false caso contrário.

$url = "https://www.exemplo.com";
if (filter_var($url, FILTER_VALIDATE_URL)) {
    echo "URL válida.";
} else {
    echo "URL inválida.";
}

$idade = 25;
$options = array("options" => array("min_range" => 18, "max_range" => 120));
if (filter_var($idade, FILTER_VALIDATE_INT, $options) !== false) {
    echo "Idade válida.";
} else {
    echo "Idade inválida.";
}

Sanitizando

A sanitização é o processo de limpar os dados de entrada, removendo ou codificando caracteres perigosos. Diferente da validação, a sanitização sempre retorna uma string modificada (ou o tipo adequado) e nunca retorna false. Os filtros de sanitização mais comuns incluem FILTER_SANITIZE_STRING (remove tags HTML e codifica caracteres especiais), FILTER_SANITIZE_EMAIL (remove caracteres não permitidos em e-mails) e FILTER_SANITIZE_URL (remove caracteres inválidos em URLs).

É importante usar a sanitização com cuidado, pois ela pode alterar dados que o usuário pretendia enviar. Por exemplo, FILTER_SANITIZE_STRING remove tags HTML, o que pode ser desejável para evitar XSS, mas se o usuário precisar enviar HTML permitido, deve-se usar uma abordagem mais específica.

$dados_sujos = "<script>alert('XSS')</script>";
$limpo = filter_var($dados_sujos, FILTER_SANITIZE_STRING);
echo $limpo; // Saída: alert('XSS') (as tags foram removidas)

$email_sujo = "usuário@exemplo.com";
$email_limpo = filter_var($email_sujo, FILTER_SANITIZE_EMAIL);
echo $email_limpo; // Saída: usuário@exemplo.com (acento removido)

Por que nunca confiar no cliente

Nunca confiar nos dados enviados pelo cliente é um princípio fundamental de segurança. Qualquer dado vindo do navegador (via formulários, cookies, headers, etc.) pode ser manipulado por um atacante. Um usuário mal-intencionado pode enviar dados maliciosos para explorar vulnerabilidades como injeção de SQL, cross-site scripting (XSS), ou até mesmo modificar campos ocultos em formulários.

Validar e sanitizar todas as entradas é a primeira linha de defesa. Além disso, nunca exiba dados não sanitizados diretamente na saída HTML, utilize funções como htmlspecialchars() para escapar caracteres especiais. Lembre-se: a validação no lado do cliente (JavaScript) é apenas para conveniência do usuário; a validação real deve sempre ser feita no servidor.

// Exemplo de validação e sanitização combinadas
$input = $_POST['campo'];
$sanitizado = filter_var($input, FILTER_SANITIZE_STRING);
if (filter_var($sanitizado, FILTER_VALIDATE_EMAIL)) {
    // processar e-mail
}

Boas práticas

Sempre valide e sanitize os dados de acordo com o contexto. Use filtros específicos em vez de genéricos. Por exemplo, para números, use FILTER_VALIDATE_INT ou FILTER_VALIDATE_FLOAT; para strings, considere usar FILTER_SANITIZE_STRING ou FILTER_SANITIZE_SPECIAL_CHARS. Além disso, evite confiar apenas na sanitização para segurança: a validação garante que os dados estão no formato esperado, enquanto a sanitização remove o que não é desejado.

Outra prática recomendada é usar a função filter_input para obter e filtrar diretamente de fontes de entrada como INPUT_GET, INPUT_POST e INPUT_COOKIE, o que simplifica o código.

Referências

Exercícios

  1. Crie um script PHP que valide se uma string fornecida é um endereço de e-mail válido usando filter_var. Exiba "Válido" ou "Inválido".

    ✓ Resposta:
    $email = "teste@exemplo.com";
    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
        echo "Válido";
    } else {
        echo "Inválido";
    }
  2. Escreva um código que sanitize uma string removendo tags HTML e caracteres especiais usando FILTER_SANITIZE_STRING. Teste com a entrada <b>Olá</b>.

    ✓ Resposta:
    $entrada = "<b>Olá</b>";
    $limpo = filter_var($entrada, FILTER_SANITIZE_STRING);
    echo $limpo; // Saída: Olá
  3. Valide se um número inteiro está entre 1 e 100 usando filter_var com opções.

    ✓ Resposta:
    $numero = 50;
    $options = array("options" => array("min_range" => 1, "max_range" => 100));
    if (filter_var($numero, FILTER_VALIDATE_INT, $options) !== false) {
        echo "Número válido.";
    } else {
        echo "Número inválido.";
    }
  4. Sanitize uma URL removendo caracteres não permitidos usando FILTER_SANITIZE_URL.

    ✓ Resposta:
    $url = "https://exemplo.com/página?nome=João";
    $url_limpa = filter_var($url, FILTER_SANITIZE_URL);
    echo $url_limpa; // Saída: https://exemplo.com/p%C3%A1gina?nome=Jo%C3%A3o
  5. Explique por que é importante não confiar nos dados do cliente e dê um exemplo de ataque que poderia ocorrer se não houver validação.

    ✓ Resposta:Nunca confiar no cliente é crucial porque qualquer dado enviado pelo navegador pode ser manipulado. Um exemplo clássico é a injeção de SQL: se um campo de pesquisa for usado diretamente em uma consulta SQL sem validação, um atacante pode inserir algo como '; DROP TABLE usuarios; -- para deletar tabelas. A validação e sanitização no servidor previnem esses ataques.