Glossário

O que é injeção de SQL (SQLi): uma falha que deixa a entrada reescrever os comandos do seu banco de dados

Injeção de SQL ocorre quando a entrada do usuário altera uma consulta ao banco. Como funciona e a defesa: prepared statements, ORMs e privilégio mínimo.

Publicado 2026-06-08 Atualizado 2026-10-06 10 min de leitura
Nesta página

Injeção de SQL é quando o texto que você digita em uma caixa de busca vira "parte de um comando" para o banco de dados. Veja como funciona e como evitá-la de forma confiável (sem passos de ataque).

Por que acontece (o mecanismo)

A causa raiz é montar SQL por concatenação de strings. Misture a entrada direto na instrução e ela pode cruzar a "fronteira de valor" e agir como comando.

✗ Concatenação de strings (perigosa)

Entrada concatenada na instrução → a entrada pode ser lida como parte do comando

✓ Placeholders (segura)

Valores passados para slots ? / $1 como dado → sempre permanecem valores

Concatene a entrada e ela cruza a fronteira de valor, mudando o comando. Com placeholders, um valor permanece um valor.

O dano é "tudo o que aquela conexão de banco pode fazer". Se o banco interno é alcançável, é uma causa clássica de vazamentos em massa, ao lado de RCE e SSRF.

Defesa

1

Use placeholders / prepared statements (o mais importante)

Não monte SQL por concatenação. Passe os valores via ? / parâmetros nomeados como 'dado'. Só isso quase elimina toda a classe.

2

Apoie-se no seu ORM / query builder

A maioria dos ORMs usa placeholders por padrão. Quanto menos SQL cru você escrever à mão, mais seguro. Se você precisar escrever SQL cru, sempre parametrize-o.

3

Usuário de banco com privilégio mínimo

Não conceda ao usuário de banco da aplicação direitos desnecessários (DROP, outras tabelas, operações de admin). Mesmo se comprometido, contenha o dano.

4

Validação de entrada como complemento

Checagens de tipo/comprimento/formato ajudam, mas não as torne sua defesa principal; elas complementam os placeholders.

A visão deste site: pare de montar SQL cru à mão, para começar

A SQLi é conhecida há muito tempo e ainda acontece, porque é "conveniente" misturar a entrada na instrução. A posição deste site é clara: nunca crie um lugar onde valores sejam concatenados em SQL. Faça dos placeholders ou de um ORM o padrão e essa vulnerabilidade é evitada por design. Não dependa do escape manual.

Atenção: placeholders só carregam valores

Placeholders não cobrem tudo. Eles carregam apenas valores — não a estrutura da consulta, como nomes de tabela, nomes de coluna ou a direção do ORDER BY (asc/desc).

Quando você precisa que isso seja dinâmico (por exemplo, deixar o usuário escolher uma "chave de ordenação" ou "coluna de filtro"), não jogue a entrada no SQL — em vez disso, selecione o nome real de uma allowlist predefinida. "Coluna de ordenação" e "coluna de filtro" são os pontos cegos clássicos onde as pessoas assumem que os placeholders as cobrem.

A entrada não é só campo de formulário

Se você acha que só caixas de busca e formulários de login exigem cuidado, vai deixar casos passar. Valores que podem acabar no SQL chegam por muitos caminhos.

  • Headers HTTP (User-Agent, X-Forwarded-For e outros) e cookies
  • Valores em JSON recebidos por uma API, ou lidos de arquivos
  • Valores salvos uma vez no banco e depois montados em SQL por outro processo

O último se chama injeção de SQL de segunda ordem. Mesmo que você tenha usado placeholders ao salvar, ela funciona quando outro processo concatena depois o valor armazenado. Não presuma que "veio do meu próprio banco, então é seguro": use placeholders em todo lugar onde SQL é montado.

A explicação deste site sobre falsificação do X-Forwarded-For descreve um caso em que strings de sondagem chegaram num header, mas a injeção de SQL não funcionou porque o valor foi passado com placeholder.

Como difere de termos parecidos

As falhas com "injeção" no nome têm uma coisa em comum: a entrada é lida como comando em outra linguagem. A diferença é onde a entrada vai parar.

TermoOnde a entrada vai pararDano principalCorreção de raiz
Injeção de SQLComandos para o banco de dados (SQL)Ler, alterar ou apagar dadosPlaceholders
XSSHTML ou JavaScript executado no navegador do usuárioAbuso da sessão do usuário, conteúdo falso na páginaEscape na saída e CSP
Injeção de comandos do SOComandos executados pelo shell do servidorExecutar qualquer comando no servidor (RCE)Use APIs que não passam pelo shell e enviam os argumentos separadamente

Injeção de SQL e XSS costumam ser citados juntos, mas o dano cai em lugares diferentes: a injeção de SQL atinge o banco de dados no servidor; o XSS atinge o navegador do usuário.

Como os placeholders se chamam nas principais linguagens

Toda linguagem importante oferece uma forma de passar os valores separadamente. Use isto como guia de qual recurso usar na sua stack.

Linguagem / bibliotecaRecurso a usar
Java (JDBC)PreparedStatement com setters de valor como setString
PHP (PDO)Prepare a instrução com prepare e passe os valores para execute
Python (DB-API)Passe os valores como segundo argumento de execute (não os embuta na string SQL)
Node.js (pg e outros)Símbolos numerados como $1, com os valores passados num array separado
C# (.NET)Adicione os valores aos Parameters do comando

Em qualquer linguagem, no momento em que você embute valores no SQL com template strings ou +, essa proteção deixa de funcionar.

Casos reais: grandes vazamentos que começaram com injeção de SQL em um produto

A injeção de SQL é conhecida há muito tempo, mas ainda causa grandes vazamentos. Os casos recentes muitas vezes começaram não em código escrito pela própria equipe, mas em um produto que ela usava.

CasoO que aconteceu
MOVEit Transfer (2023)Uma injeção de SQL em um produto de transferência de arquivos (CVE-2023-34362) foi explorada antes de existir correção, e dados de mais de 2.700 organizações foram levados, muitos deles por meio de fornecedores (→ o vazamento em massa do MOVEit)
Metabase (2026)Uma injeção de SQL sem autenticação em uma ferramenta de análise (CVE-2026-72898) foi explorada antes da correção, e várias empresas divulgaram vazamentos de dados de clientes (→ exploração e vazamentos do Metabase, em inglês)
Núcleo do WordPress (2026)Combinada com outra falha, uma injeção de SQL sem autenticação podia levar a RCE (→ o CVE-2026-63030 explicado, em inglês)

Depois do MOVEit, as agências americanas CISA e FBI publicaram em março de 2024 um alerta pedindo que os fabricantes de software eliminem a injeção de SQL, apontando as consultas parametrizadas (placeholders) como a correção. No "CWE Top 25" da MITRE, publicado em dezembro de 2025, a injeção de SQL (CWE-89) está em segundo lugar.

O que fazer depende do seu papel

Seu papelPrimeira coisa a fazer
Você escreve SQL (desenvolvedor)Pare de concatenar strings; use placeholders ou um ORM. Revise como as funções de SQL cru são usadas
Você opera produtos ou software de código aberto (operador)Verifique os CVEs e o status no KEV dos produtos que você roda e atualize para versões corrigidas. Reduza as telas de administração acessíveis pela internet
AmbosDê ao usuário de banco do app privilégio mínimo, limitado às tabelas e colunas de que ele precisa

Como verificar o seu próprio ambiente

Você não precisa digitar strings de ataque para testar isso. O código e as configurações dizem o que você precisa saber.

1

Encontre SQL montado a partir de strings

Procure no seu código linhas em que palavras-chave de SQL (SELECT, WHERE etc.) aparecem junto com concatenação de strings ou template strings. Verifique também se nenhuma entrada é concatenada em funções de SQL cru ($queryRawUnsafe, whereRaw, DB::raw, raw() e semelhantes).

2

Anote o que o usuário do banco pode fazer

Verifique quais tabelas o usuário de banco do app pode acessar e o que ele pode fazer nelas (SHOW GRANTS no MySQL, information_schema.role_table_grants no PostgreSQL). Remova direitos de exclusão desnecessários e qualquer acesso a tabelas de outros apps.

3

Compare os produtos que você usa com dados de vulnerabilidades

Use a Consulta de CVE / KEV para ver as vulnerabilidades conhecidas dos produtos que você roda e se estão sendo exploradas. Para dependências, o osv-scanner verifica todas de uma vez.

4

Garanta que erros de SQL não apareçam na tela

Em produção, confirme que as mensagens de erro do banco não são mostradas aos usuários como estão. Mantenha os erros detalhados apenas nos logs.

5

Procure sinais nos seus logs

Verifique se os erros de sintaxe do banco aumentaram de repente e se o seu WAF ou os logs de acesso mostram uma sequência de requisições da mesma origem contendo strings parecidas com SQL. Se sim, revise primeiro o código por trás dessa rota.

Fontes (primárias)

  • OWASP, "SQL Injection Prevention Cheat Sheet" (em inglês) — cheatsheetseries.owasp.org (placeholders, cuidados com stored procedures, validação de entrada por allowlist, privilégio mínimo, não depender de escape)
  • CISA e FBI, "Secure by Design Alert: Eliminating SQL Injection Vulnerabilities in Software" (25 de março de 2024, em inglês) — cisa.gov
  • MITRE, "2025 CWE Top 25 Most Dangerous Software Weaknesses" (dezembro de 2025, em inglês) — cwe.mitre.org (CWE-89 em segundo lugar)
  • IPA, "How to Secure Your Web Site" — ipa.go.jp (em japonês; soluções fundamentais vs mitigações)

Leia a seguir

Classificação

O CWE classifica os tipos de fraqueza por trás das vulnerabilidades; o MITRE ATT&CK classifica as técnicas dos atacantes. Ambos são mantidos pela MITRE e amplamente usados para rotular vulnerabilidades e regras de detecção.

ATT&CK (técnica de ataque)

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

© 2026 The MITRE Corporation. This work is reproduced and distributed with the permission of The MITRE Corporation. MITRE ATT&CK and ATT&CK are registered trademarks of The MITRE Corporation. The MITRE Corporation (MITRE) hereby grants you a non-exclusive, royalty-free license to use ATT&CK® for research, development, and commercial purposes. Any copy you make for such purposes is authorized provided that you reproduce MITRE's copyright designation and this license in any such copy. ATT&CK Terms of Use

FAQ

QO que acontece com a injeção de SQL?
A

Um invasor muda o significado de uma consulta ao banco de dados — lendo dados que deveriam estar ocultos, alterando-os ou, na pior das hipóteses, apagando tudo ou contornando a autenticação. É uma causa clássica de vazamentos massivos de dados.

QQual é a defesa mais confiável?
A

Passar valores via placeholders (prepared statements). Não monte SQL com concatenação de strings; passe os valores como 'dado' por um canal separado, para que a entrada nunca possa ser lida como comando. A maioria dos ORMs faz isso por padrão.

QEscapar a entrada é suficiente?
A

O escape manual é propenso a erros e desencorajado. Use placeholders. Dê também ao usuário do banco privilégio mínimo para limitar o dano caso algo passe.

QSe eu uso um ORM, estou seguro?
A

No uso normal, sim: os ORMs passam os valores como placeholders por padrão. Mas, se você concatenar a entrada nas funções de SQL cru que eles oferecem ($queryRawUnsafe do Prisma, whereRaw e DB::raw do Laravel, raw e extra do Django etc.), a mesma falha volta mesmo com ORM. Partes que os placeholders não conseguem carregar, como nomes de colunas de ordenação, também exigem cuidado.

QUm WAF consegue deter a injeção de SQL?
A

Ajuda a reduzir o dano, mas não é a correção de raiz. O guia 'How to Secure Your Web Site' da IPA, do Japão, também separa a solução fundamental (placeholders) das medidas que apenas reduzem o dano. O WAF é uma mitigação, e algumas entradas escapam da detecção. Use-o como medida provisória até o código ser corrigido.

QComo descubro se um produto que eu uso tem injeção de SQL?
A

Compare o nome e a versão do produto com as vulnerabilidades publicadas (CVEs) e com a lista KEV da CISA, de vulnerabilidades com exploração confirmada. A Consulta de CVE / KEV deste site faz isso. Como mostraram o MOVEit Transfer e o Metabase, injeções de SQL em produtos que as organizações usam já levaram a grandes vazamentos de dados mais de uma vez.

QO que é um prepared statement?
A

Um mecanismo em que a forma da instrução SQL (onde entram os valores) é enviada primeiro ao banco de dados, e os valores são enviados separadamente depois. Os lugares dos valores são marcados com símbolos como ? ou $1 (placeholders). Como a forma é fixada antes, os valores enviados depois nunca são lidos como comandos, sejam quais forem os caracteres que contenham.

QO que é injeção de SQL cega (blind)?
A

Um tipo de injeção de SQL em que o conteúdo do banco e os erros não aparecem na tela, mas ainda assim a informação pode ser lida aos poucos pelas diferenças nas respostas ou nos tempos de resposta. Não mostrar nada na tela não torna um site seguro. A causa e a correção são as mesmas da injeção de SQL comum: com placeholders, ela não funciona.

QEsconder as mensagens de erro evita a injeção de SQL?
A

Não. Esconder os erros torna a falha mais difícil de encontrar, mas, como mostra a injeção de SQL cega, a informação pode ser lida mesmo sem erro aparente. Você não deve mostrar erros na tela, mas, separadamente, ainda precisa corrigir todo lugar que monta SQL por concatenação de strings.

QStored procedures são seguras?
A

Escritas corretamente, são tão eficazes quanto os placeholders. Mas a OWASP alerta que, se uma procedure monta SQL dentro dela concatenando a entrada (SQL dinâmico), o mesmo problema volta. Verifique o que a procedure faz por dentro.