Saltar para o conteúdo
SQL Injection: Do Ataque à Proteção Completa
Segurança

SQL Injection: Do Ataque à Proteção Completa

20 de maio de 2026·Paulo Pereira

O que é SQL Injection?

SQL Injection ocorre quando entrada de usuário é inserida diretamente em queries SQL sem sanitização. É uma das vulnerabilidades mais antigas e ainda uma das mais exploradas — responsável por incontáveis vazamentos de dados.

Como o Ataque Funciona

# Código vulnerável
def buscar_usuario(email: str):
    query = f"SELECT * FROM usuarios WHERE email = '{email}'"
    return db.execute(query).fetchone()

Se o atacante passa como email: ' OR '1'='1

A query vira:

SELECT * FROM usuarios WHERE email = '' OR '1'='1'
-- Retorna TODOS os usuários

Ou com: '; DROP TABLE usuarios; --

SELECT * FROM usuarios WHERE email = ''; DROP TABLE usuarios; --'
-- Deleta a tabela inteira

Extração de Dados com UNION

Um ataque mais sofisticado usa UNION para extrair dados de outras tabelas:

' UNION SELECT null, table_name, null FROM information_schema.tables --

Isso retorna os nomes de todas as tabelas do banco — o primeiro passo para um vazamento completo.

Proteção 1: Parâmetros Preparados (Principal Defesa)

# Python + psycopg2
cursor.execute(
    "SELECT * FROM usuarios WHERE email = %s AND senha_hash = %s",
    (email, senha_hash)
)

# Python + SQLAlchemy
from sqlalchemy import text
result = db.execute(
    text("SELECT * FROM usuarios WHERE email = :email"),
    {"email": email}
)
// Node.js + pg
const result = await pool.query(
  'SELECT * FROM usuarios WHERE email = $1',
  [email]
);

// Node.js + mysql2
const [rows] = await conn.execute(
  'SELECT * FROM usuarios WHERE email = ?',
  [email]
);

O banco de dados trata parâmetros como dados, nunca como SQL.

Proteção 2: ORM Correto

ORMs como Sequelize, Prisma, SQLAlchemy e Hibernate protegem automaticamente — mas apenas quando usados corretamente:

// SEGURO — Prisma usa parâmetros automaticamente
const usuario = await prisma.usuario.findUnique({
  where: { email }
});

// AINDA VULNERÁVEL — raw query sem parâmetros
const usuario = await prisma.$queryRaw`SELECT * FROM usuario WHERE email = '${email}'`;

// CORRETO com raw query
const usuario = await prisma.$queryRaw`SELECT * FROM usuario WHERE email = ${email}`;
// Prisma trata ${email} como parâmetro seguro

Proteção 3: Validação de Input

from pydantic import BaseModel, EmailStr, constr

class LoginDTO(BaseModel):
    email: EmailStr  # valida formato de e-mail
    senha: constr(min_length=8, max_length=128)

# Se a validação falhar, FastAPI retorna 422 automaticamente

Proteção 4: Princípio do Menor Privilégio

O usuário do banco que a aplicação usa nunca deve ter permissões de DDL:

-- Crie um usuário específico para a aplicação
CREATE USER app_user WITH PASSWORD 'senha_forte';

-- Apenas as permissões necessárias
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;

-- NUNCA dê:
-- GRANT ALL PRIVILEGES ...
-- GRANT DROP, CREATE, ALTER ...

Proteção 5: WAF e Detecção

Um Web Application Firewall (WAF) como AWS WAF, Cloudflare ou ModSecurity detecta padrões de SQLi:

-- Padrões suspeitos que um WAF bloqueia:
' OR 1=1
'; DROP TABLE
UNION SELECT
information_schema

Configure alertas para tentativas — mesmo que o código esteja protegido, é importante saber que está sendo atacado.

Testando sua Aplicação

# sqlmap — ferramenta de pentest para SQLi
pip install sqlmap

sqlmap -u "https://app.com/api/usuarios?id=1" --level=3 --risk=2

# Para testar formulários
sqlmap -u "https://app.com/login" --data="email=test&senha=test" --dbs

Use apenas em sistemas que você tem permissão para testar.

Checklist de Proteção

  • Todas as queries usam parâmetros preparados ou ORM correto
  • Nenhuma concatenação de string com input de usuário em SQL
  • Usuário do banco tem permissões mínimas necessárias
  • Erros SQL não são expostos ao usuário (logs internos apenas)
  • WAF configurado em produção
  • Testes automatizados de segurança no CI/CD

Conclusão

SQL Injection é 100% prevenível com parâmetros preparados. Não há nenhum motivo para ter essa vulnerabilidade em código novo. Use sempre ORMs ou queries parametrizadas, e nunca concatene input de usuário em SQL.