A maioria das pessoas aprende sqlmap de trás para frente. Copiam um comando de um fórum, apontam para uma URL, veem uma parede de texto passar na tela e terminam com um dump de tabela que não sabem explicar ou com a mensagem "all tested parameters do not appear to be injectable" numa página que elas têm certeza de que é vulnerável. A ferramenta não é a parte difícil. Ler o que ela diz, sim. Antes de rodá-la contra qualquer coisa, encontre uma injeção na mão no lab Query Quake da HackerDNA para entender o que o sqlmap está automatizando.
O sqlmap automatiza a metade tediosa da injeção SQL: provar que a falha é real, identificar o banco de dados e extrair os dados caractere por caractere. Ele não encontra bugs que você já não desconfiava, e é quase inútil como scanner de descoberta. Este guia percorre um scan real, da primeira requisição até a tabela extraída, explica cada linha de saída que importa e cobre as situações em que a resposta certa é fechar o terminal. A injeção SQL continua sendo uma das falhas de injeção acompanhadas no OWASP Top 10, e é exatamente por isso que essa ferramenta segue relevante desde 2006.
Resumo: o sqlmap é uma ferramenta de código aberto que detecta e explora injeção SQL automaticamente. Aponte-a para um parâmetro do qual você já desconfia com sqlmap -u "http://alvo.example/page?id=1" --batch, leia o resumo dos pontos de injeção que ele imprime e depois enumere com --tables e --dump. Deixe --level e --risk nos valores padrão até que um scan volte vazio, e nunca rode contra um alvo para o qual você não tem permissão por escrito.
O que é o sqlmap?
sqlmap é uma ferramenta de teste de intrusão de código aberto que automatiza a detecção e a exploração de falhas de injeção SQL. Você entrega uma requisição com um parâmetro que controla, e ela descobre se esse parâmetro chega até uma consulta SQL, qual técnica vai trazer dados de volta, qual motor de banco está por trás da aplicação, e então extrai o conteúdo.
Ele é escrito em Python, licenciado sob GPLv2 e já vem instalado no Kali Linux. A versão 1.10.9 reconhece 31 motores de banco de dados, dos óbvios (MySQL, PostgreSQL, Oracle, Microsoft SQL Server, SQLite) a uma cauda longa que quase ninguém encontra em campo (Mckoi, FrontBase, Raima, eXtremeDB). Essa amplitude importa menos do que parece. Na prática, você vai ver MySQL, PostgreSQL, MSSQL e SQLite repetidamente.
O que é importante entender antes da primeira execução é o que o sqlmap não é. Ele não é um scanner de vulnerabilidades web. Não vai rastrear uma aplicação e te entregar uma lista de bugs. Ele testa os parâmetros para os quais você o apontar, e se você não fez o reconhecimento necessário para saber quais parâmetros valem o teste, está apenas gerando tráfego. A fraqueza que ele caça é a CWE-89: neutralização inadequada de elementos especiais em um comando SQL, que ficou em terceiro lugar no CWE Top 25 das fraquezas de software mais perigosas publicado pela MITRE em 2024, com pontuação de 35,88.
Se você nunca viu a versão manual do que essa ferramenta faz, leia primeiro o tutorial de injeção SQL. O sqlmap vai fazer muito mais sentido depois que você tiver digitado ' OR 1=1 -- num formulário de login e visto a consulta desmoronar.
Instale o sqlmap em menos de um minuto
No Kali Linux ele já está lá. Em qualquer outro lugar, escolha um caminho:
# Kali Linux (já instalado)
sqlmap --version
# pip, em qualquer sistema com Python 3
pip install sqlmap
# a partir do código-fonte, para acompanhar o desenvolvimento
git clone --depth 1 https://github.com/sqlmapproject/sqlmap.git
cd sqlmap
python3 sqlmap.py --version
O pacote do pip e o clone do git são o mesmo projeto; o clone apenas te dá os commits mais recentes e permite ler os scripts de tamper. O sqlmap roda em Python 2.7 e 3.x, embora não haja motivo algum para estar no 2.7 em 2026. Se instalar pelo código-fonte, note que o comando passa a ser python3 sqlmap.py em vez de sqlmap, o que trava metade das pessoas que seguem um tutorial escrito para o outro método.
Um hábito que vale adotar imediatamente: rode dentro de um ambiente virtual ou de um contêiner, e não como root. O sqlmap grava arquivos de sessão, CSVs extraídos e logs no seu diretório pessoal, e esses arquivos contêm dados de outras pessoas.
Seu primeiro scan, linha por linha
O comando útil mais simples é uma URL com um parâmetro e nada mais:
sqlmap -u "http://127.0.0.1:8099/product.php?id=1" --batch
--batch manda o sqlmap responder às próprias perguntas com a opção padrão em vez de parar para te fazer sete perguntas. Use quando já souber quais são essas perguntas. Nas primeiras vezes, deixe de fora e leia cada uma.
Foi isto que o sqlmap 1.10.9 imprimiu quando rodei esse comando contra uma página propositalmente vulnerável na minha própria máquina, reduzido às linhas que carregam informação:
[INFO] testing connection to the target URL
[INFO] checking if the target is protected by some kind of WAF/IPS
[INFO] testing if the target URL content is stable
[INFO] target URL content is stable
[INFO] testing if GET parameter 'id' is dynamic
[INFO] GET parameter 'id' appears to be dynamic
[INFO] heuristic (basic) test shows that GET parameter 'id' might be SQL injectable
[INFO] testing for SQL injection on GET parameter 'id'
[INFO] GET parameter 'id' appears to be 'AND boolean-based blind - WHERE or HAVING clause' injectable (with --string="Mug")
[INFO] heuristic (extended) test shows that the back-end DBMS could be 'SQLite'
[INFO] target URL appears to have 3 columns in query
[INFO] GET parameter 'id' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable
Quatro dessas linhas merecem ser memorizadas, porque são elas que dizem se o resto da execução significa alguma coisa.
- "target URL content is stable" significa que a página devolve o mesmo conteúdo para a mesma requisição. Se ele disser que o conteúdo não está estável, o sqlmap não consegue separar o efeito do seu payload do ruído normal da página, e todo resultado boolean-based a partir dali fica suspeito. Resolva com
--stringou--text-only. - "parameter 'id' is dynamic" significa que mudar o valor mudou a resposta. Um parâmetro que não é dinâmico normalmente nem chega a uma consulta.
- "heuristic (basic) test shows ... might be SQL injectable" é o sqlmap jogando um único caractere quebrado no parâmetro e percebendo um erro de banco. É o sinal mais rápido que você recebe, e é o que mais confirma aquilo que você já suspeitava na mão.
- "checking if the target is protected by some kind of WAF/IPS" merece atenção em trabalhos reais. Se houver um filtro na frente da aplicação, silêncio aqui não significa que não exista um.
Aquele scan inteiro consumiu 52 requisições HTTP. Guarde esse número, porque ele é a referência para uma decisão que você vai tomar mais adiante sobre --level e --risk.
Como ler o resumo dos pontos de injeção
Quando o sqlmap encontra algo, ele imprime um bloco que os iniciantes ignoram na rolagem. É a saída mais útil de toda a execução. Este é o bloco real daquele scan:
sqlmap identified the following injection point(s) with a total of 52 HTTP(s) requests:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=1 AND 6764=6764
Type: error-based
Title: SQLite >= 3.9 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (JSON path)
Payload: id=1 AND 2526=JSON_EXTRACT(CHAR(123,125),...)
Type: time-based blind
Title: SQLite > 2.0 AND time-based blind (heavy query)
Payload: id=1 AND 9391=LIKE(CHAR(65,66,67,68,69,70,71),UPPER(HEX(RANDOMBLOB(500000000/2))))
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: id=1 UNION ALL SELECT CHAR(113,106,120,112,113)||...,NULL,NULL-- FBlf
---
back-end DBMS: SQLite
Cada "Type" é uma forma diferente de arrancar uma resposta do banco, e elas não são equivalentes. Esta é a ordem que importa quando você está esperando um dump lento terminar:
- UNION query. O banco anexa suas linhas ao conjunto de resultados real e a página as imprime. Uma requisição pode trazer muitos valores. Sempre a mais rápida, sempre a preferida quando o sqlmap a encontra.
- Error-based. O banco vaza a resposta dentro de uma mensagem de erro. Quase tão rápida quanto a UNION, e funciona quando a página mostra erros mas não linhas extras.
- Boolean-based blind. A página tem dois estados visíveis, verdadeiro e falso, e o sqlmap reconstrói os dados bit a bit fazendo perguntas de sim ou não. Lenta, porém confiável.
- Time-based blind. Nada visível muda, então o sqlmap pede ao banco que demore quando a resposta for sim e cronometra o retorno. Dolorosamente lenta e facilmente atrapalhada por uma rede ocupada. Se for sua única opção, espere horas para um dump.
- Stacked queries. O parâmetro permite encerrar a instrução e executar uma segunda. Não é um método de extração por si só, mas é a porta de entrada para gravar arquivos e executar comandos.
O padrão --technique=BEUSTQ tenta todas, e o sqlmap escolhe a mais rápida disponível para cada tarefa sem que ninguém precise mandar. O motivo para conhecer a ordem mesmo assim é que ela te diz o que a aplicação está fazendo. Um alvo em que só a time-based funciona é um alvo que nunca te mostra saída, e isso molda tudo o que vem depois. Se esse for o seu caso, o guia de injeção SQL cega cobre o equivalente manual, que é o plano B quando a ferramenta não avança.
Repare na última linha: back-end DBMS: SQLite. Assim que o sqlmap sabe qual é o motor, ele para de testar payloads dos outros 30 e a execução encurta drasticamente. Se você já sabe o que o alvo roda, passe --dbms=mysql e pule essa fase inteira.
Do ponto de injeção aos dados
Detecção e extração são etapas separadas. Uma vez que o ponto de injeção está armazenado, você acrescenta as opções de enumeração e o sqlmap reaproveita o que já sabe em vez de testar de novo:
# quais bancos existem
sqlmap -u "http://alvo.example/product.php?id=1" --dbs
# tabelas de um banco
sqlmap -u "http://alvo.example/product.php?id=1" -D shopdb --tables
# colunas, para saber o que vale a pena extrair
sqlmap -u "http://alvo.example/product.php?id=1" -D shopdb -T users --columns
# os dados em si, apenas duas colunas
sqlmap -u "http://alvo.example/product.php?id=1" -D shopdb -T users -C username,password --dump
Essa ordem de escalada é proposital. Iniciantes partem para o --dump-all ou o -a (extrair tudo) já na primeira execução e depois se perguntam por que o scan está rodando há quarenta minutos e por que os logs de erro do alvo estão lotados. Desça a árvore: bancos, tabelas, colunas e então as duas ou três colunas de que você realmente precisa.
Este é o dump real do meu alvo de teste:
Table: users
[2 entries]
+----+---------------------------------------------+----------+
| id | password | username |
+----+---------------------------------------------+----------+
| 1 | 5f4dcc3b5aa765d61d8327deb882cf99 (password) | dana |
| 2 | e10adc3949ba59abbe56e057f20f883e (123456) | ravi |
+----+---------------------------------------------+----------+
[INFO] table 'users' dumped to CSV file '/root/.local/share/sqlmap/output/127.0.0.1/dump/users.csv'
Olhe os parênteses. O sqlmap reconheceu aqueles valores como hashes MD5, ofereceu um ataque de dicionário e quebrou os dois com a wordlist embutida. É um detalhe genuinamente bom, e também um lembrete de quão rápido MD5 sem sal cai. A última linha também importa: tudo o que o sqlmap recupera é gravado em disco, dentro do seu diretório pessoal. Num trabalho real, aquele arquivo passa a ser uma evidência pela qual você responde.
Duas opções merecem entrar na memória muscular aqui. --count diz quantas linhas uma tabela tem antes de você se comprometer com o dump, o que evita começar uma extração cega de 400 mil registros. E --where="id<10" permite puxar uma amostra representativa em vez da tabela inteira, o que normalmente é tudo o que um relatório precisa.
As opções que realmente mudam seus resultados
O sqlmap tem centenas de parâmetros. Seis deles cobrem quase tudo o que você vai fazer no primeiro ano.
-r: carregar uma requisição de um arquivo
É a opção mais útil da ferramenta e a que os tutoriais mencionam por último. Em vez de remontar uma requisição complexa na linha de comando com --data, --cookie e quatro -H, capture a requisição no Burp Suite, salve num arquivo e entregue o arquivo:
sqlmap -r login-request.txt -p username --batch
Cada cabeçalho, cookie e parâmetro de corpo vai junto exatamente como o navegador enviou. Para qualquer coisa atrás de um login, para APIs JSON ou formulários multipart, essa é a única abordagem sensata. Adicione --force-ssl se a requisição salva não registrar o esquema.
-p: nomear o parâmetro
Sem -p, o sqlmap testa todos os parâmetros que encontrar, incluindo cookies e cabeçalhos nos níveis mais altos. Se o seu reconhecimento aponta que o bug está em search, diga isso. Um teste focado termina numa fração do tempo e gera uma fração do barulho.
--level e --risk: não mexa neles no começo
Aqui vai a opinião forte: o reflexo de abrir com --level 5 --risk 3 está errado, e é o erro mais comum de iniciantes com essa ferramenta. Essas opções controlam quantos payloads o sqlmap tenta e quão perigosos eles podem ser.
Eu medi. Contra um parâmetro que não é injetável, o sqlmap 1.10.9 executou 11 grupos de teste nos valores padrão (--level 1 --risk 1) e 172 com --level 5 --risk 3, mantendo todo o resto igual. São cerca de quinze vezes mais testes para chegar à mesma resposta, e num alvo lento isso transforma uma verificação de dois minutos numa pausa para o café. Pior: o nível de risco 3 inclui payloads baseados em OR que podem casar com todas as linhas de uma tabela, o que num DELETE ou UPDATE é como se apagam dados sem querer durante um teste autorizado.
Rode com o padrão. Se o parâmetro parece mesmo injetável e volta limpo, aí sim aumente o nível, um degrau por vez. O nível 2 acrescenta o teste de cookies, o nível 3 acrescenta User-Agent e Referer, e o nível 5 testa cabeçalhos que a maioria das aplicações nunca coloca numa consulta.
--tamper: quando um filtro deforma seu payload
Se um filtro de entrada remove espaços ou normaliza palavras-chave, o payload que funciona na mão pode nunca chegar intacto. Os scripts de tamper reescrevem payloads em formas equivalentes, e a 1.10.9 traz 84 deles:
sqlmap -u "http://alvo.example/p?id=1" --tamper=space2comment,randomcase --batch
space2comment troca espaços por /**/, randomcase varia a caixa das palavras-chave, between substitui operadores de comparação. Rode --list-tampers para ler todos. Não empilhe seis de uma vez na esperança de acertar: escolha o que corresponde ao comportamento de filtragem que você observou, porque os scripts de tamper alteram o payload de formas que podem quebrar uma injeção que já funcionava.
--batch e o arquivo de sessão
Na primeira vez que você rodar o sqlmap de novo contra o mesmo alvo, vai ver isto:
[INFO] resuming back-end DBMS 'sqlite'
sqlmap resumed the following injection point(s) from stored session:
O sqlmap guarda tudo o que aprende num arquivo de sessão SQLite por alvo. É por isso que a segunda execução termina na hora, e também por isso que um resultado desatualizado pode te acompanhar depois que a aplicação muda. --flush-session limpa e recomeça do zero. Se um scan está se comportando de um jeito sem sentido, esvaziar a sessão é a primeira coisa a tentar.
--threads: velocidade com cuidado
Extração cega é uma requisição por caractere, então --threads 5 pode de fato encurtar um dump longo. Acima de 10 você está martelando o alvo, e numa infraestrutura de produção é assim que um teste vira uma indisponibilidade. Cinco é um teto razoável para trabalho autorizado.
Para ir além: a folha de referência do sqlmap lista o guia completo de comandos por tarefa, incluindo as opções de acesso a arquivos e shell do sistema que este artigo deixa de fora de propósito.
Quando o sqlmap diz "não injetável" e você sabe que é injetável
Esse é o momento que manda as pessoas para os fóruns. Você achou o bug manualmente, o sqlmap discorda, e a tentação é aumentar todas as opções ao máximo. Em vez disso, percorra esta lista na ordem.
- Você não enviou uma sessão válida. De longe a causa mais comum. O sqlmap recebeu um redirecionamento de login em cada requisição e concluiu, obedientemente, que nada era injetável. Use
-rcom uma requisição autenticada capturada. - O parâmetro não é o que você pensa. Acrescente
-pe nomeie-o explicitamente. Se ele vive dentro de JSON ou de um cookie, o-rcuida da posição corretamente. - A resposta é instável. Carimbos de data, tokens CSRF ou anúncios rotativos mudam a página a cada requisição, então o sqlmap não consegue comparar respostas. Dê a ele uma âncora:
--string="Bem-vindo"para um texto que só aparece nas respostas verdadeiras, ou--text-onlypara ignorar a marcação. - Um token anti-CSRF está rejeitando cada requisição. Aponte o sqlmap para ele com
--csrf-token=nome_do_tokene ele vai buscar um novo antes de cada requisição. - Um filtro está reescrevendo o payload. Agora sim é hora do
--tamper, e agora sim é hora de aumentar o--level. Não antes. - A injeção é de segunda ordem. O payload é armazenado numa página e executado quando outra página o renderiza. O sqlmap trata esse caso com
--second-url, mas você precisa saber que a segunda página existe, e nenhum scanner vai te contar isso.
Existe também a possibilidade honesta de que o parâmetro esteja corretamente parametrizado e você tenha se enganado. Isso acontece mais do que os tópicos de fórum sugerem, e vale confirmar em vez de escalar por mais uma hora. Uma consulta preparada não deixa nenhuma brecha para o sqlmap, e nenhuma combinação de opções muda isso.
Vale usar o sqlmap em CTFs?
Iniciantes devem usar o sqlmap em CTFs? Não nos dez primeiros desafios. Automatizar uma habilidade que você nunca executou na mão te deixa incapaz de distinguir um achado real de um falso positivo, e incapaz de seguir quando a ferramenta trava. Resolva desafios web na mão até conseguir montar um payload UNION sozinho, e só então deixe o sqlmap assumir a extração repetitiva.
Há um motivo prático além do pedagógico. O sqlmap está na lista de ferramentas restritas do exame OSCP, ao lado de outras ferramentas de exploração automatizada; o objetivo declarado da OffSec é avaliar sua capacidade de identificar e explorar vulnerabilidades, não de automatizar o processo. Se o seu plano inclui essa certificação, cada hora gasta rodando sqlmap em vez de escrever payloads é uma hora de preparo que você não fez. As regras atuais estão no guia do exame OSCP, e elas mudam de tempos em tempos, então confira antes de prestá-lo.
Onde o sqlmap ganha seu lugar num CTF é no momento seguinte à descoberta. Você provou que existe uma injeção boolean-based blind e agora precisa tirar 400 caracteres de uma tabela, um bit por vez. Fazer isso na mão não é aprender, é digitar. Esse é o trabalho para o qual a ferramenta foi construída.
Mais um hábito separa quem evolui de quem estaciona: depois que o sqlmap encontra algo, leia o payload que ele usou. Está impresso no resumo dos pontos de injeção. Descubra por que AND 6764=6764 prova alguma coisa, e por que o payload UNION tem três NULL. Essa é a lição inteira, e ela está na saída de toda execução bem-sucedida.
Perguntas frequentes
É legal usar o sqlmap?
A ferramenta em si é legal e de código aberto. Rodá-la contra um sistema que você não possui e para o qual não tem autorização por escrito não é, e na maioria das jurisdições configura acesso não autorizado, independentemente de você ter extraído dados ou não. O sqlmap imprime esse aviso a cada execução por um motivo. Pratique em alvos propositalmente vulneráveis, plataformas de treino dedicadas ou sistemas cobertos pelo escopo de um programa de bug bounty.
O sqlmap funciona em requisições POST e APIs?
Sim. Use --data="username=admin&password=x" para envios de formulário simples, ou capture a requisição completa com um proxy e passe com -r request.txt para qualquer coisa mais complexa. A versão 1.10.9 também lida com corpos JSON, endpoints GraphQL com --graphql, e consegue derivar alvos direto de uma especificação OpenAPI com --openapi.
Quanto tempo deve durar um scan do sqlmap?
A detecção em um único parâmetro GET com as configurações padrão costuma levar menos de um minuto; minha execução de referência consumiu 52 requisições HTTP. Já a extração depende inteiramente da técnica. Um dump por UNION de uma tabela pequena leva segundos. A mesma tabela por injeção time-based blind, a cerca de uma requisição por bit com 5 segundos de atraso em cada, pode rodar por horas. Se um dump está se arrastando, veja qual técnica o sqlmap escolheu antes de culpar a ferramenta.
Qual a diferença entre --level e --risk?
--level (1 a 5) controla quantos payloads o sqlmap tenta e onde ele procura, acrescentando cookies no nível 2 e cabeçalhos a partir do nível 3. --risk (1 a 3) controla o quanto esses payloads podem ser perigosos, sendo que o nível 3 inclui payloads baseados em OR capazes de afetar todas as linhas de uma tabela. Aumente o level quando um scan voltar vazio. Aumente o risk apenas quando entender o que o payload pode fazer com os dados.
O sqlmap consegue dar um shell no servidor?
Às vezes. --os-shell e --sql-shell existem, mas exigem condições raras num alvo moderno e endurecido: suporte a stacked queries, um usuário de banco com privilégios altos e um caminho gravável conhecido dentro da raiz web. Trate-os como um bônus ocasional num trabalho autorizado, não como uma etapa do seu fluxo padrão, e entenda que eles gravam arquivos num sistema que é apenas emprestado a você.
Considerações legais e éticas
Lembrete essencial: sempre obtenha autorização explícita por escrito antes de testar qualquer sistema. O sqlmap envia consultas malformadas por natureza, e níveis de risco mais altos podem modificar ou destruir dados. "Eu só estava testando" não é defesa.
- Confirme o escopo por escrito antes da primeira requisição: quais hosts, quais parâmetros e em quais horários.
- Mantenha
--riskem 1 a menos que o cliente tenha aceitado explicitamente a possibilidade de modificação de dados. - Extraia o mínimo necessário para provar o impacto. Uma linha de uma tabela sensível demonstra a falha; a tabela inteira é um vazamento causado por você.
- Os dados extraídos caem no seu disco em CSV puro. Criptografe, reporte e depois apague.
- Em programas de bug bounty, leia primeiro as regras sobre ferramentas automatizadas. Vários programas grandes proíbem scanners automáticos por completo, e o sqlmap conta como um.
Para o lado defensivo da mesma moeda, a referência da OWASP sobre injeção SQL e a folha de dicas de parametrização de consultas são o material para entregar ao seu time de desenvolvimento.
Seus próximos passos
Aprender a usar o sqlmap bem é, na maior parte, aprender a ler quatro linhas da saída dele: o conteúdo está estável, o parâmetro é dinâmico, qual técnica ele escolheu e qual banco está por trás. Todo o resto são opções. As pessoas que ficam boas em injeção SQL são as que encontraram o bug na mão primeiro e usaram a ferramenta para pular a digitação, não as que aprenderam a ferramenta esperando que ela encontrasse bugs por elas.
Faça nessa ordem. Comece pelo Query Quake, onde você monta o payload UNION e vê exatamente quais colunas voltam. Depois siga o caminho guiado do curso Web Attacks, que cobre injeção junto com o resto do OWASP Top 10 em labs no navegador, sem nada para instalar. Os dois são gratuitos para começar, sem cartão de crédito. Quando você conseguir achar a injeção sem ajuda, volte ao sqlmap e deixe que ele faça a parte chata.
Parte da série OWASP Top 10
Artigos relacionados: