Introdução: por que seu site em PHP pode ser invadido agora mesmo?
\nImagine a situação: você criou um site legal em PHP, formulário de contato, comentários, área do usuário. Tudo funciona. Mas um dia você entra no painel administrativo e está vazio. Ou pior: apareceu propaganda de cassino no site e o Google bloqueou seu recurso. Familiar? A raiz do mal é o tratamento incorreto da entrada do usuário.
\nA pergunta "How can I sanitize user input with PHP?" é uma das mais populares no Stack Overflow. Milhares de desenvolvedores tropeçam nos mesmos erros. Neste artigo, vamos analisar os principais erros que até programadores experientes cometem e mostrar como evitá-los. Você aprenderá como se proteger contra XSS, injeções SQL e outros ataques. Vamos lá!
\n\nErro nº1: Usar mysql_real_escape_string() para tudo
\nEscola antiga: muitos desenvolvedores ainda pensam que se envolverem todos os dados em mysql_real_escape_string(), o problema está resolvido. Isso é um erro grave. Esta função é destinada apenas para escapar strings em consultas SQL, e ainda assim para a extensão obsoleta mysql_*, que foi removida já no PHP 7.
Exemplo de código incorreto:
\n<?php\n$name = mysql_real_escape_string($_POST['name']);\n$query = "INSERT INTO users (name) VALUES ('$name')";\n$result = mysql_query($query);\n?>\nPor que isso é ruim:
\n- \n
- A função não protege contra ataques XSS (por exemplo, inserção de JavaScript). \n
- A extensão
mysql_*está obsoleta e é insegura. \n - Você mistura a lógica de escape com a lógica de negócios. \n
Como corrigir: use consultas preparadas (prepared statements) através de PDO ou MySQLi. E para exibir dados na tela, use uma sanitização separada.
\n\nErro nº2: Ignorar ataques XSS ao exibir dados
\nO erro mais comum. Você recebe os dados, salva no banco de dados e simplesmente os exibe com echo ou print. Pronto — um invasor pode inserir um script que rouba cookies, redireciona o usuário ou estraga o layout.
Exemplo de código vulnerável:
\n<?php\necho "<p>Olá, " . $_GET['name'] . "!</p>";\n?>\nSe na URL for passado ?name=<script>alert('XSS')</script>, o script será executado.
Solução: use a função htmlspecialchars() com o parâmetro ENT_QUOTES:
<?php\n$name = htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8');\necho "<p>Olá, " . $name . "!</p>";\n?>\nImportante: a sanitização deve ser feita no momento da exibição, não ao salvar. Se você substituir os caracteres no banco de dados, perderá os dados originais.
\n\nErro nº3: Filtragem cega com strip_tags()
\nMuitos pensam: "Ah, vou simplesmente remover todas as tags HTML e pronto". Mas strip_tags() não é uma solução mágica. Primeiro, ela remove apenas as tags, mas mantém os atributos (por exemplo, onclick). Segundo, se você precisar permitir algumas tags (como <b> ou <i>), o strip_tags() se torna inconveniente.
Exemplo:
\n<?php\n$comment = strip_tags($_POST['comment']);\necho $comment; // Remove <script>, mas mantém <a onclick="...">\n?>\nSolução: use htmlspecialchars() para texto comum ou bibliotecas como HTML Purifier, se precisar permitir tags específicas. O HTML Purifier verifica não apenas tags, mas também atributos, estilos e até CSS.
Erro nº4: Ausência de validação de email, URL e números
\nSanitização não é só sobre XSS. Se você espera um email e recebe a string "123", isso pode causar erros. Ou se você salva uma URL sem verificação, um invasor pode inserir javascript:alert(1).