Banco de dúvidas
Como se proteger da injeção de SQL
A injeção de SQL é um dos ataques mais comuns e perigosos direcionados a aplicações web. Esse tipo de ataque ocorre quando um invasor consegue inserir uma consulta SQL maliciosa dentro de uma entrada de dados que é então executada pelo banco de dados do servidor.
Se bem-sucedido, um ataque de injeção SQL pode resultar na exposição de dados sensíveis, corromper ou apagar dados ou até mesmo assumir o controle total de um sistema.
Como ocorre a injeção de SQL?
Dando um exemplo bem básico em PHP (poderia ser outra linguagem), suponha que você tenha um formulário de login em seu site que solicite um nome de usuário e uma senha. Quando um usuário fornece suas informações, uma consulta SQL pode ser formada assim:
$sql = "SELECT * FROM usuarios WHERE usuario='$usuario' AND senha='$senha'";
Nesse caso o atacante pode inserir algo como ' OR '1'='1 no campo de nome de usuário ou senha, e a consulta SQL resultante seria assim:
$sql = "SELECT * FROM usuarios WHERE usuario='' OR '1'='1' AND senha='' OR '1'='1'";
Neste caso, '1'='1' sempre será verdadeiro, tornando a autenticação inútil e permitindo acesso ao atacante!
ATENÇÃO! Novamente, o exemplo acima é simples e apenas ilustrativo, mas há muitos tipos de injeção de SQL possíveis. Por isso as precauções a seguir são importantes: elas frustram praticamente qualquer tipo de injeção SQL.
Protegendo-se contra a injeção de SQL
Felizmente, há maneiras eficazes de proteger suas aplicações PHP contra ataques de injeção de SQL.
1. Consultas preparadas e declarações parametrizadas
As consultas preparadas e declarações parametrizadas garantem que os dados inseridos por um usuário sejam sempre tratados como dados literais, e não como parte do código SQL. Isso impede a injeção de SQL.
Aqui está um exemplo de como você pode fazer isso usando MySQLi:
// Conexão com o banco de dados $mysqli = new mysqli('localhost', 'usuario', 'senha', 'banco_de_dados'); // Preparando a consulta $stmt = $mysqli->prepare("SELECT * FROM usuarios WHERE usuario=? AND senha=?"); // Substituindo os parâmetros $stmt->bind_param('ss', $usuario, $senha); // Executando a consulta $stmt->execute();
No exemplo acima, os '?' são substituídos pelos valores de $usuario e $senha. Como são tratados como dados literais, quaisquer tentativas de injeção de SQL serão ineficazes.
2. Escapar entradas do usuário
Outra técnica comum para evitar a injeção de SQL é "escapar" todas as entradas do usuário, onde se insere barras invertidas (\) antes de caracteres como aspas simples e duplas, entre outros. No PHP, a função mysqli_real_escape_string() é comumente usada para isso.
$usuario = mysqli_real_escape_string($conn, $usuario); $senha = mysqli_real_escape_string($conn, $senha);
Essa função ajuda a garantir que quaisquer caracteres especiais na entrada do usuário sejam tratados como caracteres literais.
Em resumo, ao programar consultas SQL que aceitam valores fornecidos pelos usuários, sempre trate esses parâmetros como possivelmente maliciosos, não os inserindo em quaisquer consultas sem o devido tratamento.