"Eu só escapo as aspas": por que seu código está vulnerável
\n\nSe 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\nMas 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.
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\nErro #1: Acreditar cegamente em "sanitização" como solução universal
\n\nO 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\nO 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\nO 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\nErro #2: Usar funções obsoletas (ou aplicá-las incorretamente)
\n\nVamos 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
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\nO 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\nViu? Nenhuma sanitização para SQL. Apenas parâmetros. O banco de dados decide o que é dado e o que é comando.
\n\nErro #3: Confundir validação com sanitização
\n\nMuitos 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.
Validação — verifica se a entrada corresponde ao formato esperado (email, número, URL). Se não, rejeite.
\n\nSanitização — remove ou altera caracteres indesejados, mas apenas quando realmente necessário (por exemplo, para nomes de arquivo).
\n\nExemplo 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\nRegra 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\nErro #4: Ignorar o contexto de saída (XSS)
\n\nVocê salvou os dados no banco usando prepared statements. Ufa, sem SQL injection. Mas aí