Pular para o conteúdo
Categoria: Pentest9 min de leitura

SQL Injection na Pratica: Explorando, Detectando e Mitigando em Lab Controlado

Por Lucas Andrade ·

Demonstracao tecnica de SQLi com sqlmap em ambiente proprio, focando em deteccao defensiva e fixes parametrizados que realmente seguram o trafego em producao.

SQL Injection na Pratica: Explorando, Detectando e Mitigando em Lab Controlado

SQL Injection completou 27 anos em 2026 e continua no top tres do OWASP, nao porque os atacantes ficaram mais espertos, e sim porque ORMs mal usados, queries dinamicas em dashboards internos e resolvers GraphQL que concatenam strings continuam indo para producao. Este guia monta um lab controlado onde voce explora, detecta e mitiga a vulnerabilidade de ponta a ponta. O objetivo nao e exibir um dump da tabela users: e entender o ciclo completo, do primeiro probe ate uma regra WAF que mata o sqlmap em menos de dois minutos. Tudo roda em hardware seu, contra alvos que voce tem autorizacao de quebrar, numa rede isolada sem rota para nada real.

O que e SQL injection de verdade

SQL injection acontece quando input nao confiavel chega ao interpretador SQL como codigo em vez de dado. O banco nao consegue distinguir a intencao do desenvolvedor do payload do atacante quando os dois ficam colados no mesmo string. O exemplo canonico e "SELECT * FROM users WHERE id = " + req.id, onde id=1 OR 1=1 transforma uma busca de uma linha em leitura completa da tabela. A causa raiz nunca e o motor do banco; e a concatenacao. Frameworks modernos tornam a parametrizacao o padrao, mas a montagem crua de strings sobrevive em endpoints de relatorio, clausulas dinamicas ORDER BY, filtros de busca e query builders feitos a mao.

A taxonomia das classes de injection

Voce nao testa o que nao consegue nomear. In-band UNION-based devolve dados direto na resposta HTTP por um UNION SELECT anexado. Boolean-based blind infere um bit de cada vez a partir de como a pagina muda quando uma condicao e verdadeira ou falsa. Time-based blind usa SLEEP() ou pg_sleep() para vazar dados pela latencia quando nao ha saida visivel. Error-based induz o banco a ecoar dados dentro de uma mensagem de erro. Out-of-band exfiltra por DNS ou HTTP quando o canal e totalmente cego. E second-order armazena um payload que dispara depois, em outra query, em outra rota. Aplicacoes reais costumam expor mais de uma classe.

Montando o lab isolado

Comece com Docker numa rede host-only. Rode uma instancia DVWA, MySQL 8.0 com o binlog ativo e um proxy Burp Suite capturando cada request. Um compose minimo da um alvo repetivel: docker compose up -d dvwa mysql. Roteie o navegador pelo Burp, coloque o nivel de seguranca em low na primeira passada, depois suba para medium e high para sentir como o filtro de input muda o jogo. Nunca exponha esse stack numa interface roteavel; labs de SQLi atraem scanners oportunistas, e um MySQL vulneravel na internet publica vira o cryptominer de um desconhecido em questao de horas.

Exploracao passo a passo com sqlmap

O primeiro experimento bate no endpoint GET do DVWA. Rode sqlmap -u 'http://lab.local/vulnerabilities/sqli/?id=1&Submit=Submit' --cookie='PHPSESSID=...; security=low' --batch --technique=BEUST --level=3 --risk=2. Em cerca de quatro segundos o sqlmap confirma injection boolean-based blind no parametro id; em onze enumera o banco dvwa e suas tabelas. Adicione --dump -T users para extrair credenciais, ou --os-shell onde privilegios FILE e secure_file_priv permitirem escrever uma web shell. Observe os payloads no fio: 1 AND 4523=4523, 1 AND 1=2 UNION SELECT NULL,NULL. Esses literais numericos repetitivos, o user-agent default sqlmap/1.8.x e o header Accept-Encoding ausente sao exatamente o sinal que voce vai armar depois para deteccao.

Exploracao manual, porque ferramentas perdem contexto

Automatize a descoberta, mas explore na mao quando importa. Para extracao UNION-based, primeiro ache o numero de colunas com ORDER BY 5-- - ate a query quebrar, depois case tipos com UNION SELECT 1,2,3,4,5-- - e coloque @@version, database() e group_concat(table_name) em colunas visiveis via information_schema.tables. Para blind boolean, bissecte cada caractere com AND ASCII(SUBSTRING((SELECT ...),1,1))>77. Para time-based, troque a comparacao por AND IF(condition, SLEEP(3), 0). Fazer isso na mao uma vez ensina o modelo mental que nenhum scanner da, e e o unico jeito de lidar com contextos mutilados por WAF onde os tamper scripts do sqlmap ficam curtos.

Second-order injection: o bug que scanners pulam

Cadastre via formulario um usuario chamado admin'-- cujo prepared statement escapa a aspa com seguranca na escrita. O payload fica dormente no banco. O problema mora num endpoint interno de busca ou perfil que reusa esse valor armazenado numa query dinamica sem reparametrizar. Resultado: bypass de autenticacao numa rota que nunca apareceu no scan inicial, porque o payload so detona em outro contexto. E o mesmo modo de falha que fura APIs GraphQL cujos resolvers compartilham um query builder. Ferramentas automaticas raramente pegam isso, por isso revisao manual de codigo continua pagando aluguel em todo engagement serio.

Deteccao e instrumentacao

Transforme o barulho do atacante em sinal. Ative SET GLOBAL general_log = 'ON' para que cada statement caia no query log com timestamp em microssegundos. Compare trinta segundos de trafego legitimo com trinta de sqlmap: o coeficiente de variacao do tamanho da query salta de cerca de 0.12 para 1.8, e os erros de sintaxe disparam. Envie o log via Filebeat para o Elastic e construa tres deteccoes: erros de sintaxe SQL acima de cinco por minuto por IP de origem, sequencias com UNION SELECT NULL, e tempo de execucao acima de tres desvios padrao do baseline horario. Contra sqlmap com --random-agent e --delay=2, as tres dispararam em menos de noventa segundos. Plante tambem honeytokens: uma coluna falsa credit_card_test com string rastreavel diz exatamente qual endpoint vazou no dia em que ela aparecer num paste site.

Mitigacao e hardening que realmente segura

Mitigacao real comeca com prepared statements parametrizados e nao termina ai. Troque strings interpolados por parametros ligados em cada linguagem: NamedParameterJdbcTemplate em Java, placeholders $1 no pgx do Go, e PDO com PDO::ATTR_EMULATE_PREPARES=false em PHP para evitar o classico bypass de aspa multibyte. Como prepared statements nao parametrizam identificadores, proteja o ORDER BY dinamico e nomes de coluna com um allowlist estrito. Some least privilege no usuario da aplicacao (GRANT SELECT, INSERT, UPDATE apenas, nunca FILE ou SUPER), validacao de input na borda, e um WAF como ModSecurity com CRS 4.x em modo blocking na frente. Reduza a superficie antes de confiar em deteccao; defesa em profundidade significa que o atacante precisa vencer cada camada, nao so uma.

Armadilhas comuns

Times quebram as proprias defesas de formas previsiveis. Parametrizam o valor mas interpolam o nome da tabela. Confiam num ORM e depois descem para uma query crua num relatorio. Escapam na saida em vez de parametrizar na entrada. Rodam o usuario da app como root no banco, entao uma injection menor vira comprometimento total do servidor. Testam so o formulario de login e ignoram busca, export e paineis admin onde o SQL dinamico feio se esconde. E tomam um scan verde do sqlmap como prova de seguranca, quando o sqlmap por design nunca reporta os caminhos second-order e de logica de negocio que um revisor humano encontra.

Um checklist de campo

Antes de assinar: toda query que toca input externo esta parametrizada; identificadores passam por um allowlist; o usuario do banco tem least privilege; mensagens de erro sao genericas e nunca ecoam SQL; um WAF bloqueia em producao, nao so loga; o query log alimenta um SIEM com as tres deteccoes acima; ha honeytokens em tabelas de alto valor; e uma revisao trimestral cobre todo endpoint que aceita input, incluindo rotas internas e de admin. Prove que o ciclo funciona atacando o seu proprio build e vendo os alertas dispararem.

Alem do MySQL: outros motores mudam os payloads

A classe do bug e portavel, a sintaxe nao, e um tester que so conhece MySQL congela no momento em que o backend e PostgreSQL ou SQL Server. No PostgreSQL a concatenacao usa ||, os comentarios usam --, os atrasos vem de pg_sleep(3), e as stacked queries costumam estar disponiveis via driver, o que abre a porta para execucao de comandos com COPY ... TO PROGRAM em instalacoes mal configuradas. No SQL Server WAITFOR DELAY '0:0:3' conduz a inferencia time-based, xp_cmdshell e a escalacao classica quando habilitado, e a extracao error-based se apoia em conflitos de tipo com CONVERT(). O Oracle forca cada SELECT a passar por FROM dual e tambem concatena com ||. Stores NoSQL tambem nao sao seguros: o MongoDB aceita injecao de operadores como {"$gt": ""} quando um body JSON passa sem validacao para uma query, transformando um login num match sempre verdadeiro. A licao defensiva e identica em todos, por isso generaliza: nunca construa a query a partir do input, faca bind sempre, e rode a conta do banco com o grant mais estreito possivel para que nem uma injection bem sucedida alcance o sistema operacional.

FAQ

Um ORM me deixa imune a SQL injection? Nao. ORMs parametrizam o caminho comum, mas escapes de query crua, fragmentos SQL nativos e clausulas WHERE ou ORDER BY construidas dinamicamente reintroduzem a vulnerabilidade. Audite cada lugar onde seu ORM deixa voce descer para SQL cru.

Um WAF sozinho basta? Nao. Um WAF compra tempo e bloqueia tooling comum, mas truques de encoding, tamper scripts e payloads second-order driblam regras de assinatura. Trate o WAF como uma camada sobre queries parametrizadas e least privilege, nunca como substituto.

Takeaway pratico: monte o lab, rode o sqlmap uma vez para sentir o ritmo dos payloads, e gaste oitenta por cento do tempo restante em deteccao e fixes. SQL injection nao e problema de criatividade do atacante; e uma query dinamica que ninguem revisou. Parametrize tudo que for valor, use allowlist para tudo que for identificador, e o dia que voce conseguir provar que sua aplicacao mata sqlmap em menos de dois minutos com bloqueio automatico, voce ganhou.

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly