Artigos sobre: Solução de Problemas
Este artigo também está disponível em:

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

Este artigo foi útil?

Compartilhe seu feedback

Cancelar

Obrigado!