Seu código PHP na mira: por que o silêncio não é uma opção
\n\nImagine: você lançou um site, tudo funciona perfeitamente, os clientes estão satisfeitos. Enquanto isso, em algum canto escuro da internet, um script kiddie digita na sua barra de pesquisa a string mágica ' OR 1=1 --. E o banco de dados, como um servo obediente, entrega todas as senhas dos usuários. História familiar? Infelizmente, para muitos desenvolvedores iniciantes, sim.
Segurança em PHP não é uma burocracia chata, mas sim a proteção real do seu tempo, dinheiro e reputação. Hoje vamos abordar os dois maiores inimigos das aplicações web: SQL Injection e Cross-Site Scripting (XSS). Você aprenderá a identificá-los, neutralizá-los e nunca mais deixá-los passar no seu código.
\n\nSQL Injection: quando o usuário se torna um hacker
\n\nSQL Injection é um ataque onde o invasor "injeta" código SQL malicioso através de campos de entrada. Se você simplesmente insere os dados do usuário na consulta, considere que você mesmo abriu a porta para o ladrão.
\n\nComo é um código vulnerável
\n\nAqui está um exemplo clássico que ainda aparece em tutoriais antigos e em sites ativos:
\n\n<?php\n// PERIGOSO! Nunca faça isso\n$username = $_POST['username'];\n$password = $_POST['password'];\n\n$query = "SELECT * FROM usuarios WHERE username = '$username' AND password = '$password'";\n$result = mysqli_query($conn, $query);\n?>\n\nO que acontece se no campo username for inserido admin' --? A consulta se torna:
SELECT * FROM usuarios WHERE username = 'admin' --' AND password = ''\n\nO hífen duplo -- comenta o restante da consulta. Voilà — o invasor entra como admin sem senha. E se ele digitar '; DROP TABLE usuarios; --? Adeus, usuários.
Salvando a pátria: Prepared Statements
\n\nA melhor forma de se proteger contra SQL Injection é usar prepared statements com PDO ou MySQLi. Eles separam a lógica da consulta dos dados, então o código malicioso nunca será executado.
\n\nVeja como fica um código seguro com PDO:
\n\n<?php\n// SEGURO! Usando prepared statements\n$username = $_POST['username'];\n$password = $_POST['password'];\n\n$stmt = $pdo->prepare("SELECT * FROM usuarios WHERE username = :username AND password = :password");\n$stmt->execute(['username' => $username, 'password' => $password]);\n$user = $stmt->fetch();\n?>\n\nAgora, mesmo que o invasor envie admin' OR 1=1 --, o PDO tratará isso como uma string comum, e não como parte do comando SQL. O banco de dados dirá: "Procurando um usuário com esse nome estranho". E não encontrará.
Por que PDO e não mysql_*?
\n\n- \n
- Segurança por padrão: O PDO escapa os dados automaticamente. \n
- Flexibilidade: Suporta diferentes SGBDs (MySQL, PostgreSQL, SQLite). \n
- Placeholders nomeados: O código fica mais legível e fácil de manter. \n
- Abordagem orientada a objetos: Um estilo de programação moderno. \n
As funções mysql_* foram removidas no PHP 7.0, e isso é um avanço. Se você ainda usa mysqli_real_escape_string — é melhor que nada, mas o PDO continua sendo mais confiável.
Ataques XSS: quando o código se esconde nos comentários
\n\nCross-Site Scripting (XSS) é a injeção de código JavaScript em uma página através da entrada do usuário. Imagine: um usuário deixa um comentário e, em vez de texto, escreve:
\n\n<script>alert('Seu site foi hackeado!');</script>\n\nSe você exibir isso sem tratamento, cada visitante verá uma janela pop-up. E se, em vez de alert, houver um código que rouba cookies ou redireciona para um site de phishing?
Tipos de ataques XSS
\n\n- \n
- Refletido (Reflected): O código malicioso