Curso
A injeção de SQL (ou SQLi, para abreviar) é um dos truques mais antigos do manual do hacker, mas ainda é incrivelmente comum e incrivelmente perigoso. Em resumo, trata-se de enganar um banco de dados para que ele revele coisas que não deveria.
Neste artigo, mostrarei a você o que é realmente a injeção de SQL, as diferentes maneiras como os invasores a utilizam, alguns exemplos reais que causaram sérios danos e, talvez o mais importante, como você pode evitá-la. Seja você um desenvolvedor ou apenas um curioso sobre como as coisas quebram na Internet, você terá uma sólida compreensão do SQLi (sem cair no sono no meio do caminho, eu prometo).
O que é injeção de SQL?
A injeção de SQL é um tipo de ataque que ocorre quando alguém encontra uma maneira de interferir nas consultas SQL que seu aplicativo envia ao banco de dados. Normalmente, essas consultas devem fazer coisas como buscar o perfil de um usuário ou atualizar uma listagem de produtos. Mas com o SQLi, um invasor pode injetar partes mal-intencionadas de código SQL nos campos de entrada (como barras de pesquisa ou formulários de login) e, de repente, o banco de dados está fazendo exatamente o que ele deseja.
Por que isso funciona?
Porque, em algum ponto da linha, o aplicativo está confiando demais na entrada do usuário e tratando-a como texto inofensivo em vez de código executável em potencial. É como deixar alguém preencher um formulário e depois colar o que ele escreveu diretamente em um console de comando.
Por que isso é ruim?
A injeção de SQL é perigosa porque pode ser usada para visualizar ou roubar dados privados (como nomes de usuário, senhas ou informações de cartão de crédito), contornar telas de login, excluir ou modificar dados e até mesmo assumir o controle total do servidor de banco de dados nos piores cenários.
Portanto, sim, o SQLi é ruim e não é nem mesmo uma preocupação de segurança recente, mas você ficaria surpreso ao ver quantos aplicativos não estão devidamente protegidos contra ele.
Tipos de injeção de SQL
Dependendo de como o invasor interage com seu aplicativo e do tipo de feedback que ele obtém, o SQLi é oferecido em alguns sabores diferentes. Há três tipos principais com os quais você pode se deparar:
SQLi em banda
Esse é o tipo mais simples. O invasor envia uma consulta SQL mal-intencionada e recebe os resultados de volta por meio do aplicativo. É rápido e geralmente muito eficaz.
-
SQLi baseado em erros: Essa técnica depende do fato de o banco de dados retornar mensagens de erro de forma útil. Esses erros podem revelar uma tonelada de informações úteis, como nomes de tabelas ou a estrutura de consultas, o que torna mais fácil para o invasor planejar seu próximo movimento.
-
SQLi baseado em união: Aqui, o invasor usa o operador
UNION
para combinar sua própria consulta com a que seu aplicativo está executando. É uma maneira inteligente de extrair dados extras do banco de dados e inseri-los na resposta.
SQLi inferencial (também conhecido como SQLi cego)
Este é mais sorrateiro. Em vez de ver os resultados de sua consulta diretamente, o invasor observa como o aplicativo se comporta para descobrir o que está acontecendo nos bastidores.
- SQLi baseado em booleano (baseado em conteúdo): O invasor ajusta a consulta com condições que são verdadeiras ou falsas (como 1=1 ou 1=2) e observa como a página muda. Ele carrega normalmente? Você está mostrando um erro? Você está agindo de forma estranha?
- SQLi baseado em tempo: Essa técnica adiciona atrasos de tempo à consulta (por exemplo,
WAITFOR DELAY '00:00:05'
) e usa o tempo de resposta para inferir se uma condição é verdadeira.
SQLi fora de banda (também conhecido como quando as coisas ficam sofisticadas)
Esse é menos comum, mas ainda assim vale a pena conhecer. O SQLi fora de banda não depende de respostas imediatas do aplicativo. Em vez disso, o invasor usa canais alternativos, como solicitações de DNS ou HTTP, para extrair dados. Geralmente é reservado para situações em que o feedback direto não é possível, mas o servidor do banco de dados tem acesso à Internet (e, em 90% dos casos, provavelmente não deveria ter).
Técnicas comuns de injeção de SQL
Então, aprendemos sobre três tipos de injeção de SQL. Mas como os invasores conseguem fazer isso na prática?
OU 1=1 ataque
Este é um clássico. Imagine um formulário de login em que você deve digitar seu nome de usuário e senha. Um invasor pode digitar algo assim:
' OR 1=1 --
A consulta SQL acaba tendo a seguinte aparência:
SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = '';
Como 1=1
é sempre verdadeiro, o banco de dados retorna todos os usuários, e o --
transforma o restante da consulta em um comentário. Se não houver limite, o invasor poderá fazer login mesmo sem saber um nome de usuário válido.
Fonte: vmware
Injeção de comentários
Como visto acima, os caracteres--
ou /* */
são usados para comentar partes de uma instrução SQL. Os invasores usam isso para remover cláusulas extras que possam quebrar a carga útil injetada. Por exemplo, se você não conhece a estrutura completa da consulta original, pode simplesmente cortá-la e torná-la sintaticamente válida novamente.
Instruções SQL em lote
Alguns bancos de dados permitem que várias instruções SQL sejam executadas em uma única solicitação, separadas por ponto e vírgula. Esse recurso pode ser usado por hackers para causar todos os tipos de danos, como modificar dados ou até mesmo descartar tabelas, se o aplicativo não restringir isso.
'; DROP TABLE users; --
Ataques baseados em UNION
Ao injetar uma instruçãoUNION SELECT
, os invasores podem combinar sua consulta mal-intencionada com a legítima e recuperar resultados de outras tabelas, como dados confidenciais do usuário, senhas ou informações de cartão de crédito. Basicamente, você está usando uma consulta existente para obter dados de bônus.
Injeção cega de SQL
Já mencionamos isso antes. Mesmo quando o aplicativo não mostra erros ou não retorna resultados de consultas, os invasores ainda podem extrair dados pouco a pouco observando o comportamento. É mais lento e tedioso, mas funciona. Isso geralmente é automatizado usando ferramentas que podem tentar centenas de consultas e respostas baseadas em tempo.
Injeção de SQL armazenado
O SQL malicioso é salvo no banco de dados, como em um perfil de usuário ou comentário, e executado posteriormente quando alguém visualiza esses dados.
Ataques de injeção de SQL no mundo real
A injeção de SQL pode parecer coisa de hacker de nicho, mas causou danos muito reais ao longo dos anos. E por danos, quero dizer milhões de registros de usuários expostos, multas enormes e manchetes que não favoreceram os departamentos de marketing.
Guess.com (2002)
Esse é um dos primeiros exemplos que fez com que as pessoas começassem a prestar atenção. Um pesquisador de segurança explorou uma falha de injeção de SQL e obteve acesso a mais de 200.000 registros de clientes, incluindo detalhes de cartões de crédito. A boa notícia é que ele foi encontrado e relatado por um hacker ético.
Sistemas de pagamento Heartland (2009)
Essa foi uma violação maciça que afetou um processador de pagamentos e mais de 130 milhões de números de cartões de crédito foram roubados. Os invasores usaram a injeção de SQL para se estabelecerem e, a partir daí, aumentaram a escala. Essa é frequentemente citada como uma das maiores violações de dados de todos os tempos.
Yahoo! Voices (2012)
Os invasores exploraram uma falha de injeção de SQL baseada em UNION e expuseram 450.000 nomes de usuário e senhas de texto simples. Sim, você leu certo, apenas credenciais brutas em texto simples. Essa violação foi especialmente constrangedora porque o Yahoo! era uma grande empresa de tecnologia, e armazenar senhas não criptografadas é uma atitude que você não deve tomar, mesmo para os padrões de 2012.
TalkTalk (2015)
O TalkTalk é um provedor de telecomunicações de alto nível do Reino Unido que foi vítima de um ataque de injeção de SQL bastante básico. Cerca de 157.000 registros de clientes foram comprometidos, e a empresa foi multada em £400.000. Um dos agressores tinha apenas 17 anos de idade.
Gab (2021)
Os hacktivistas usaram injeção de SQL para exfiltrar 70 GB de dados, incluindo postagens privadas e senhas com hash. A violação teve uma carga política e as consequências Spark ainda mais o exame minucioso da postura geral de segurança do Gab.
Como evitar a injeção de SQL
Ok, agora que já nos assustamos um pouco com todas essas violações do mundo real, vamos falar de soluções. A boa notícia é que a prevenção da injeção de SQL não é uma ciência de foguetes. Na maioria das vezes, trata-se de não confiar na opinião do usuário e aderir às práticas recomendadas. Aqui está o que você pode fazer:
Usar consultas parametrizadas
Essa é a regra número um. Nunca crie consultas SQL colando cadeias de caracteres. Em vez disso, use espaços reservados e passe as entradas do usuário como parâmetros. A maioria das estruturas e bibliotecas torna isso muito fácil.
Por exemplo, no Node.js com pg (PostgreSQL):
client.query('SELECT * FROM users WHERE id = $1', [userId]);
Basicamente, isso diz ao banco de dados, "Aqui está a estrutura da consulta e aqui estão alguns dados, por favor, não os misture".
Use procedimentos armazenados de forma inteligente
Os procedimentos armazenados podem ajudar, mas somente se eles também evitarem o SQL dinâmico. A ideia é que a lógica SQL esteja no banco de dados e que seu aplicativo apenas chame essas partes seguras e predefinidas da lógica.
Se você quiser aprender a criar, atualizar e executar funções e procedimentos armazenados, dê uma olhada em nosso curso Writing Functions and Stored Procedures in SQL Server.
Validar e higienizar a entrada
Se o seu aplicativo espera um número, certifique-se de que seja um número. Não aceite cegamente tudo o que o usuário oferece a você. Use verificações de tipo, limites de comprimento e listas de permissão (por exemplo, permitindo apenas valores bons conhecidos) sempre que possível.
O uso de caracteres de escape (como aspas) também pode ajudar, mas não substitui as consultas parametrizadas.
Use um firewall de aplicativo da Web (WAF)
Um WAF pode atuar como uma primeira linha de defesa, especialmente contra padrões de ataque conhecidos. Ele pode ajudar a bloquear algum tráfego mal-intencionado antes mesmo que ele chegue ao seu aplicativo. Não é infalível, mas é útil, é um pouco como um filtro de spam para seu SQL.
Aplicar o princípio do menor privilégio
Seu aplicativo Web não deve se conectar ao banco de dados com direitos de administrador. Limite o que cada usuário ou serviço pode fazer. Por exemplo, se o seu aplicativo só precisa ler dados, não dê a ele permissão para excluir tabelas. Quanto menos potência você tiver, menos danos uma injeção poderá causar.
Teste e detecção de injeção de SQL
Mesmo que você ache que seu código é seguro, vale a pena testá-lo como um invasor faria. A injeção de SQL tem uma maneira de passar despercebida, especialmente em grandes bases de código ou sistemas legados. Há ferramentas e técnicas que facilitam muito a detecção e são bastante divertidas de usar.
Teste manual
Às vezes, a maneira mais rápida de identificar um buraco é simplesmente cutucá-lo. Tente inserir ' OR 1=1 -- or '; DROP TABLE users; --
em campos de formulário, URLs ou quaisquer outras áreas de entrada e veja como o aplicativo reage. Se você receber erros estranhos, dados inesperados ou mensagens de sucesso misteriosas, talvez tenha encontrado algo suspeito.
Dica profissional: Sempre teste em um ambiente de desenvolvimento ou de preparação.
Scanners automatizados
Há muitas ferramentas que farão isso por você. Alguns são bons:
- sqlmap: Uma ferramenta de código aberto que automatiza a detecção e a exploração (em contextos de testes éticos).
- Burp Suite: Excelente para segurança de aplicativos da Web em geral, com extensões para detecção de SQLi.
- OWASP ZAP: Gratuito e fácil de usar para iniciantes, foi desenvolvido para encontrar todos os tipos de vulnerabilidades na Web.
Essas ferramentas simulam ataques, sinalizam possíveis pontos de injeção e, às vezes, podem sugerir correções.
Análise de registro
Outro truque sorrateiro: monitore os logs do banco de dados. Consultas repetidas que falharam, padrões de sintaxe estranhos ou um aumento de solicitações com ', --
,
ou UNION SELECT
são sinais de alerta.
Conclusão
A injeção de SQL não vai desaparecer tão cedo, e é uma daquelas ameaças que nunca envelhecem. É simples, poderoso e, se você não tomar cuidado, pode causar sérios danos. O fato é que a SQLi é totalmente evitável. Usando consultas parametrizadas, validando entradas, aplicando o princípio do menor privilégio e testando regularmente, você pode proteger seus aplicativos e seus usuários contra o impacto devastador de um ataque de injeção de SQL.
Lembre-se de que ninguém espera perfeição, mas com um pouco de esforço proativo, você pode manter seu banco de dados seguro e riscar isso da sua lista de verificação de segurança. E se você leva SQL a sério e quer mostrar suas habilidades a possíveis empregadores, dê uma olhada na nossa Certificação SQL Associate! Ele mostrará que você é capaz de usar o SQL para extrair dados apropriados de um banco de dados e usá-lo para responder a perguntas comuns sobre dados.
Perguntas frequentes
A injeção de SQL pode ser usada para atacar bancos de dados NoSQL?
A injeção de SQL tradicional não funciona em bancos de dados NoSQL, como o MongoDB, mas ataques semelhantes ao estilo de injeção podem ocorrer se as entradas não forem devidamente higienizadas (como injeções de documentos ou manipulação de consultas).
Como as estruturas modernas ajudam a evitar a injeção de SQL?
Muitas estruturas modernas (como Django, Laravel ou Spring) incluem proteções integradas, como camadas ORM e parametrização automática, que dificultam a gravação acidental de consultas vulneráveis. Mas você ainda precisa usá-los corretamente!
Os aplicativos móveis também correm o risco de sofrer injeção de SQL?
Com certeza. Se um aplicativo móvel se comunica com uma API de back-end que cria consultas SQL inseguras com base na entrada do usuário, ele é igualmente vulnerável, mesmo que o front-end pareça estar bloqueado.
Como os invasores encontram sites vulneráveis para atacar com injeção de SQL?
Eles geralmente usam scanners automatizados ou "Google dorking" (consultas de pesquisa especiais) para encontrar páginas com campos de entrada ou parâmetros de URL que possam ser exploráveis.