Guia de tecnologias

Como proteger seu banco de dados contra SQL Injection

• 6 min read • Segurança • Atualizado 27 Sep 2025
Proteja bancos de dados contra SQL Injection
Proteja bancos de dados contra SQL Injection

Diagrama de SQL Injection ilustrando entrada maliciosa sendo injetada em uma consulta e o impacto no banco de dados

O que é SQL Injection (definição curta)

SQL Injection é uma técnica de ataque em que comandos SQL maliciosos são inseridos em entradas de uma aplicação para manipular a consulta executada no banco de dados. Em uma linha: é tratar dados do usuário como código.

Por que isso é perigoso

  • Pode devolver dados sensíveis (ex.: credenciais, PII).
  • Pode modificar ou apagar tabelas inteiras.
  • Pode permitir elevação de privilégios ou execução remota em alguns cenários.

Importante: ataques funcionam apenas quando a aplicação constrói consultas SQL concatenando diretamente dados não confiáveis.

Como um ataque típico acontece

Um formulário de login que monta uma string SQL com os valores enviados pelo usuário é um alvo clássico. Exemplo vulnerável em PHP (não use em produção):

Se um atacante enviar ' OR 'a'='a no campo de senha, a condição se tornará sempre verdadeira e o acesso pode ser concedido sem credenciais válidas.

Principais vetores e variações

  • Error-based: o atacante força o banco a retornar mensagens de erro detalhadas para descobrir a estrutura do banco.
  • Union-based: usa UNION para combinar resultados e exfiltrar dados.
  • Blind SQL Injection: o atacante não recebe resultados diretos, mas infere dados por testes booleanos ou temporizadores.
  • Out-of-band: usa canais externos (DNS, HTTP) para extrair dados.

Estratégias de defesa (camadas)

A proteção eficaz usa várias camadas. Nenhuma técnica isolada é 100% segura.

1) Consultas parametrizadas (prepared statements) — prioridade

Prepared statements separam o código SQL dos dados do usuário. Use sempre que possível.

Exemplo com PDO (PHP) — recomendado:

prepare('SELECT * FROM users WHERE username = :username AND user_password = :password');
$stmt->execute([':username' => $_POST['username'], ':password' => $_POST['password']]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>

Exemplo com MySQLi (PHP):

prepare('SELECT * FROM users WHERE username = ? AND user_password = ?');
$stmt->bind_param('ss', $_POST['username'], $_POST['password']);
$stmt->execute();
$result = $stmt->get_result();
?>

Exemplo em Python com psycopg2 (Postgres):

cur.execute('SELECT * FROM users WHERE username = %s AND user_password = %s', (username, password))

Observação: prepared statements tratam entradas como dados, não como parte do SQL, eliminando a maior parte das injeções.

2) Validação e sanitização de entradas

  • Validação: verifique tipo, tamanho, formato (whitelisting preferível). Ex.: e-mail deve corresponder a regex básica, IDs devem ser inteiros.
  • Sanitização: remova espaços em excesso, caracteres de controle, quebras de linha. Use com cautela — nunca confie só em escaping.
  • Evite construir SQL concatenando strings com dados do usuário.

Exemplo de validação simples em PHP:

if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
  // rejeitar entrada
}
$id = intval($_GET['id']); // força número inteiro

3) Escaping (quando necessário)

Escaping (ex.: mysqli_real_escape_string) pode reduzir risco, mas não substitui prepared statements. Útil em contexts legados onde prepared statements não são possíveis.

4) Princípio do menor privilégio (least privilege)

  • Cada aplicação/serviço deve usar uma conta de banco de dados com apenas os direitos necessários (SELECT, INSERT, UPDATE específicos), não a conta SA/root.
  • Separe contas para leitura e escrita quando aplicável.

Exemplo (Microsoft SQL Server):

deny select on sys.tables to sqldatabasepermit;
deny select on sys.packages to sqldatabasepermit;
deny select on sys.sysobjects to sqldatabasepermit;

5) Trate erros com cuidado

Não exponha mensagens de erro detalhadas ao usuário final — registros internos podem conter detalhes úteis para depuração, mas devem ser protegidos.

6) Camadas adicionais

  • ORM (Object-Relational Mapping): frameworks bem projetados reduzem risco ao gerar consultas seguras, mas verifique pontos onde consultas brutas são usadas.
  • Stored procedures: podem ajudar se parametrizadas corretamente; não use procedures que concatenam strings SQL internamente.
  • Web Application Firewall (WAF): filtro adicional para detectar padrões de ataque.

Arquiteturas, heurísticas e mental models

  • Mental model: pense em dados como toxina — sempre contenha-os com barreiras (validação, parametrização, privilégios mínimos).
  • Heurística: “Never trust user input” — trate tudo como hostil até provar o contrário.

Checklist rápido para desenvolvedores e DBAs

  • Todas as consultas que usam dados externos usam prepared statements.
  • Campos são validados por tipo, tamanho e formato (whitelist).
  • Contas de banco seguem princípio do menor privilégio.
  • Mensagens de erro amigáveis ao usuário; logs detalhados internos e protegidos.
  • Revisões de código e testes automatizados para injeção.
  • Monitoramento e alertas para atividades anômalas (padrões de consulta, longos tempos de execução).

Playbook de resposta a incidente (resumo)

  1. Isolar a aplicação/endpoint afetado.
  2. Reverter a partir de backup conhecido e limpo se houver corrupção de dados.
  3. Rodar análise forense: logs de aplicação, logs do banco, conexões recentes.
  4. Bloquear credenciais ou rotacionar chaves afetadas.
  5. Aplicar correções (ex.: converter consultas vulneráveis para prepared statements).
  6. Notificar stakeholders e, se aplicável, cumprir obrigações regulatórias.

Importante: mantenha backups imutáveis e registre táteis (audit logs) para investigação.

Quando as defesas podem falhar (contraexemplos)

  • Aplicação usa ORM mas permite SQL bruto concatenado em algumas rotas — risco persiste.
  • Prepared statements são usados, mas entradas usadas em cláusulas dinâmicas (ORDER BY, table names) são concatenadas sem validação.
  • Erros de configuração: conta do app tem privilégios elevados por erro operacional.

Testes e aceitação

Critérios de aceitação:

  • Todas as rotas que aceitam input externo passam em testes automatizados de injeção (SAST/DAST + fuzzing).
  • Sem mensagens de erro SQL detalhadas para usuários.
  • Contas com privilégios restringidos documentadas.

Casos de teste recomendados:

  • Teste booleano: injetar ' OR '1'='1 e garantir que não retorna dados indevidos.
  • Teste de union: injetar payloads com UNION e verificar bloqueio/nenhum dado sensível retornado.
  • Teste de tempo (blind): injetar operações que dormem (quando aplicável) e checar comportamento.

Maturidade: níveis rápidos

  • Nível 1 (Inicial): consultas concatenadas, pouca ou nenhuma validação.
  • Nível 2 (Intermediário): validação básica, alguns prepared statements, logs básicos.
  • Nível 3 (Maduro): prepared statements em toda a entrada, least privilege, WAF, testes automáticos SAST/DAST, resposta a incidente definida.

Perguntas frequentes (FAQ)

O escaping é suficiente para prevenir SQL injection?

Escaping reduz risco, mas não é tão robusto quanto prepared statements. Use escaping apenas em contextos legados; migre para prepared statements.

ORM elimina a necessidade de validar entradas?

Não. ORM ajuda, mas validação continua necessária para dados semânticos (ex.: tamanhos, formatos) e para evitar construção de SQL dinâmico inseguro.

Devo bloquear mensagens de erro do banco de dados?

Sim: mostre mensagens genéricas ao usuário e registre detalhes sensíveis em logs internos com acesso restrito.

Resumo final

SQL Injection continua sendo uma das ameaças mais comuns a aplicações que usam bancos relacionais. A defesa eficaz combina práticas de desenvolvimento seguro (prepared statements, validação por whitelist), arquitetura segura (least privilege, segregação de contas), proteção em camadas (WAF, ORM, stored procedures) e processos operacionais (testes, monitoramento, playbooks de incidente). Adote prepared statements como regra, valide tudo, minimize privilégios e teste continuamente.

Extras: papel por papel — checklist resumido

Desenvolvedor:

  • Usar prepared statements em todas as consultas.
  • Validar e higienizar entrada (whitelist).
  • Evitar SQL dinâmico.

DBA/Administrador:

  • Criar contas com privilégios mínimos.
  • Monitorar queries incomuns e logs de auditoria.

Equipe de Segurança:

  • Automação de SAST/DAST, pentests periódicos.
  • Configurar WAF e integrar alertas.
Autor
Edição

Materiais semelhantes

Instalar e usar Podman no Debian 11
Containers

Instalar e usar Podman no Debian 11

Apt‑pinning no Debian: guia prático
Administração de sistemas

Apt‑pinning no Debian: guia prático

Injete FSR 4 com OptiScaler em qualquer jogo
Tecnologia

Injete FSR 4 com OptiScaler em qualquer jogo

DansGuardian e Squid com NTLM no Debian Etch
Infraestrutura

DansGuardian e Squid com NTLM no Debian Etch

Corrigir erro de instalação no Android
Android

Corrigir erro de instalação no Android

KNetAttach: Pastas de Rede remota no KDE
KDE

KNetAttach: Pastas de Rede remota no KDE