Sanitização de entrada do usuário em PHP: principais erros e proteções

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

"Eu só escapo as aspas": por que seu código está vulnerável

\n\n

Se você já pesquisou no Google "How can I sanitize user input with PHP?", não está sozinho. Essa pergunta no Stack Overflow acumulou centenas de milhares de visualizações. E não é surpresa: segurança é um dos tópicos mais quentes no desenvolvimento web.

\n\n

Mas eis o paradoxo: a maioria das respostas para essa pergunta está desatualizada ou é perigosa. Desenvolvedores ainda escrevem coisas como mysql_real_escape_string() (que já não existe há 10 anos) ou simplesmente removem caracteres "perigosos". Spoiler: isso não funciona.

\n\n

Neste artigo, vamos analisar os 5 principais erros de sanitização de entrada do usuário em PHP que transformam seu site em um ralo, e mostrar como corrigi-los de uma vez por todas.

\n\n

Erro #1: Acreditar cegamente em "sanitização" como solução universal

\n\n

O maior erro é pensar que existe uma única função que "limpa" qualquer dado. Veja o código típico de um iniciante:

\n\n
<?php\n$nome = $_POST['nome'];\n$nome = strip_tags($nome);\n$nome = addslashes($nome);\n// Agora os dados estão seguros? Não!\n?>
\n\n

O problema é que contextos diferentes exigem tratamentos diferentes. Validação (verificação de formato) e sanitização (limpeza) não são a mesma coisa. E ainda existe o escape de saída, que ocorre em outro lugar.

\n\n

O que fazer: Defina o que você fará com os dados em cada etapa. Para o banco de dados, uma coisa; para HTML, outra; para JSON, uma terceira.

\n\n

Erro #2: Usar funções obsoletas (ou aplicá-las incorretamente)

\n\n

Vamos revisar os "dinossauros" da segurança em PHP:

\n\n
    \n
  • mysql_real_escape_string() — removida no PHP 7.0. Esqueça.
  • \n
  • addslashes() — não protege contra todas as SQL injections, especialmente com codificações multibyte.
  • \n
  • strip_tags() — remove tags, mas não escapa a saída. XSS ainda é possível através de atributos.
  • \n
\n\n

Exemplo de código perigoso que ainda aparece:

\n\n
<?php\n$id = $_GET['id'];\n$id = addslashes($id);\n$query = "SELECT * FROM usuarios WHERE id = '$id'";\n// Se id = 1 OR 1=1 -- você foi hackeado\n?>
\n\n

O que fazer: Use prepared statements (consultas preparadas). Esta é a única maneira confiável de se proteger contra SQL injection.

\n\n
<?php\n$stmt = $pdo->prepare("SELECT * FROM usuarios WHERE id = :id");\n$stmt->execute(['id' => $_GET['id']]);\n?>
\n\n

Viu? Nenhuma sanitização para SQL. Apenas parâmetros. O banco de dados decide o que é dado e o que é comando.

\n\n

Erro #3: Confundir validação com sanitização

\n\n

Muitos pensam: "Vou remover todos os caracteres suspeitos e ficará seguro". Mas isso quebra a lógica da aplicação. Imagine que o usuário digitou a senha P@ssw0rd! e você removeu os caracteres @ e !. A senha virou Pssw0rd — e o usuário não consegue mais entrar.

\n\n

Validação — verifica se a entrada corresponde ao formato esperado (email, número, URL). Se não, rejeite.

\n\n

Sanitização — remove ou altera caracteres indesejados, mas apenas quando realmente necessário (por exemplo, para nomes de arquivo).

\n\n

Exemplo de validação correta de email:

\n\n
<?php\n$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);\nif ($email === false) {\n    // Email inválido — não salvar, não exibir\n    echo "Digite um email válido";\n    exit;\n}\n// Agora $email é uma string segura para qualquer finalidade\n?>
\n\n

Regra de ouro: Se você espera um número — verifique se é um número. Se espera um email — verifique o formato. Todo o resto — rejeite.

\n\n

Erro #4: Ignorar o contexto de saída (XSS)

\n\n

Você salvou os dados no banco usando prepared statements. Ufa, sem SQL injection. Mas aí

Blogs

Book Recommendations