SQL injection: O que é e como se proteger?
O que é SQL Injection?
O SQL Injection (SQLi) continua no topo das vulnerabilidades mais perigosas da web por um motivo simples: ele é fácil de explorar e devastador para o negócio. O ataque acontece quando a aplicação aceita dados do usuário e, em vez de tratá-los apenas como informação, acaba concatenando tudo direto na string da consulta SQL. Com isso, o banco interpreta o texto malicioso como se fosse uma ordem do próprio sistema.
Se o seu sistema junta variáveis de formulários ou URLs direto na query, você basicamente abriu a porta para que qualquer um acesse, modifique ou apague seus dados sensíveis.
O ataque na vida real
Pensando em um sistema de autenticação comum, a aplicação recebe o e-mail digitado e monta a busca. Se um atacante preencher o campo de e-mail com o seguinte valor:
'admin@exemplo.com' OR '1'='1'
A query processada pelo servidor vai ficar assim:
SELECT * FROM usuarios WHERE email = 'admin@exemplo.com' OR '1'='1' AND senha = '...';
Como a condição '1'='1' é sempre verdadeira, o banco de dados ignora o restante da validação. O atacante consegue burlar a checagem da senha e ganha acesso direto à conta do administrador.
Como proteger seu código passo a passo
A regra de ouro do desenvolvimento seguro é universal: nunca confie no que vem do usuário. Abaixo, veja como aplicar as principais defesas usando Node.js e Python.
Consultas Parametrizadas (Prepared Statements)
Essa é a linha de defesa mais importante. Em vez de montar strings dinâmicas, você define a estrutura da query primeiro e passa os dados do usuário como argumentos isolados. O driver do banco de dados garante que esses parâmetros sejam tratados estritamente como valores textuais, neutralizando qualquer comando oculto.
Exemplo em JavaScript (Node.js + pacote pg)
// DO JEITO ERRADO: Concatenação perigosa
const query = `SELECT * FROM usuarios WHERE email = '${req.body.email}'`;
const result = await pool.query(query);
// DO JEITO CERTO: O driver isola o conteúdo de $1
const query = 'SELECT * FROM usuarios WHERE email = $1';
const values = [req.body.email];
const result = await pool.query(query, values);
Exemplo em Python (driver psycopg2)
# DO JEITO ERRADO: Formatação de string gera a query antes do envio
query = f"SELECT * FROM usuarios WHERE email = '{user_input}'"
cursor.execute(query)
# DO JEITO CERTO: Os dados vão separados da estrutura da query
query = "SELECT * FROM usuarios WHERE email = %s"
cursor.execute(query, (user_input,))
Nota: Mesmo que o Python use %s ou ? no texto da query, isso não é uma interpolação comum de strings. O driver envia o comando e os parâmetros em canais separados para o banco.
Validação e Sanitização da Entrada
Barrar o problema antes mesmo que ele chegue perto do banco de dados economiza processamento e aumenta a segurança. Garanta que o dado recebido segue o formato esperado pela aplicação.
Validação em Node.js
// Forçando a conversão para garantir um número inteiro na rota
const userId = parseInt(req.params.id, 10);
if (isNaN(userId)) {
return res.status(400).json({ error: "ID inválido." });
}
Validação em Python
import re
# Checando o formato do e-mail com expressão regular antes de usar na busca
email_pattern = r"^[\w\.-]+@[\w\.-]+\.\w+$"
if not re.match(email_pattern, user_input):
raise ValueError("Formato de e-mail inválido.")
Ecossistema de ORMs Atualizados
Ferramentas de ORM modernas lidam com a parametrização de forma nativa por baixo dos panos na maior parte das chamadas.
- No ecossistema JS (Sequelize, Prisma): Consultas estruturadas via
User.findOne({ where: { email } })já nascem protegidas. - No ecossistema Python (SQLAlchemy, Django ORM): Métodos como
User.objects.filter(email=user_input)barram o SQLi automaticamente.
Fique atento se precisar escrever queries brutas (raw SQL) dentro desses frameworks. Funções como db.execute("SELECT...") perdem a proteção automática e exigem parametrização manual idêntica aos exemplos anteriores.
Substituir a concatenação de strings por consultas parametrizadas resolve a imensa maioria dos riscos de SQL Injection. Unir essa prática com a validação rigorosa dos payloads recebidos blinda o ecossistema e garante a integridade dos dados da aplicação.
Atualizado em: 30/06/2026
Obrigado!
