MQTT (Message Queuing Telemetry Transport)

MQTT (Message Queuing Telemetry Transport) is a lightweight, publish‑subscribe messaging protocol designed for devices with limited resources and unreliable networks - a staple of the IoT landscape. Created in 1999 by Andy Stanford‑Clark (IBM) and Arlen Nipper (Eurotech) to monitor pipelines over satellite links, MQTT prioritized minimal bandwidth and power usage

MQTT Versions & Important RFCs

| MQTT Version | Standard / RFC | Status & Highlights | |--------------|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------| | 3.1.1 | OASIS v3.1.1 (ISO/IEC 20922) | Defines 14 Control Packet types, connect flags, QoS levels, clean session, keepalive, etc. | | 5.0 | OASIS v5.0 (March 2019) | Adds rich features: Reason Codes, User Properties, Enhanced AUTH, Shared subscriptions, Message Expiry, Subscription Identifiers | | RFC 9431 | MQTT + ACE OAuth‑based Authn/Z | Defines how MQTT can leverage ACE OAuth 2.0 frameworks, PoP keys, TLS, for constrained clients | | MQTT‑SN | Sensor‑Network variant (v1.2) | Supports publish/subscribe over non‑TCP transports like UDP, Zigbee |

MQTT Control Packets: What fields they have

MQTT communication occurs through structured packets with specific fields—some fixed, some conditional by version:

CONNECT

  • Protocol Name (“MQTT”), Version (4 for 3.1.1, 5 for v5)
  • Connect Flags: Clean Start/Session, Will Flag/QoS/Retain, Username, Password
  • Keep Alive: client’s ping interval
  • Properties (v5): SessionExpiryInterval, Authentication data, Request/Topic Identifiers

CONNACK

  • Acknowledge Flags: Session Present
  • Reason Code (v5): indicates success or specific failure
  • Properties (v5): Assigned Client ID, Server Keep Alive, Maximum Packet Size

PUBLISH

  • Flags: DUP, QoS (0,1,2), RETAIN
  • Topic Name: hierarchical string (e.g., home/livingroom/temperature)
  • Packet Identifier: for QoS > 0
  • Properties (v5): Message Expiry Interval, Payload Format, User Props…

SUBSCRIBE / SUBACK

  • Packet Identifier
  • Topic Filters + Options (QoS, No Local, Retain As Published, Retain Handling)
  • Reason Codes: Success, failure, QoS granted

UNSUBSCRIBE / UNSUBACK

  • Similar structure; indicate which filters to drop

PINGREQ / PINGRESP

  • Keep‑alive heartbeat, no variable header or payload

DISCONNECT / AUTH (v5)

  • Reason Code, optional properties for advanced protocol negotiation/security

Field Value Constraints

  • Protocol Version: 4 or 5
  • Flags: binary bits (true/false)
  • QoS levels:
    • 0 - "At most once" (fire-and-forget)
    • 1 - "At least once" (with ACK)
    • 2 - "Exactly once" (2-step handshake)
    Retain, Clean Start, Will Flag: boolean bits
  • Keep Alive, Packet Identifier, Expiry Time: unsigned 16/32-bit integers per spec
  • Reason Codes (v5): standardized integer codes
  • User-defined Properties: UTF-8 key/value pairs

These constraints are critical when fuzzing. Slight deviations (invalid QoS, missing flags, malformed identifiers) can reveal broker or client-side parsing flaws.

Python Libraries for MQTT

Penzzer for testing MQTT devices

Penzzer is a fuzzing automation platform capable of generating and mutating protocol messages, observing device response or crashes, and identifying edge-case behavior.

How Penzzer handles MQTT:

  1. Schema-aware fuzzing: Uses knowledge of CONNECT, PUBLISH, SUBSCRIBE packet formats & fields.
  2. Field-level mutations:
    • Invalid QoS values (e.g., 3 or negative)
    • Malformed UTF-8 in Topic Names, excessive length
    • Unusual flag combinations: Will Flag set without Will Topic
    • Unexpected properties in MQTT v5
  3. State sequencing:
    • Connection hijacking: sending PUBLISH before CONNECT
    • Repeated CONNECT without prior DISCONNECT
    • PINGREQ flooding, rapid SUBSCRIBE/UNSUBSCRIBE
  4. Authentication testing:
    • Invalid credentials method
    • Using ACE protocol (RFC 9431 profile) with malformed PoP keys or tokens
  5. Monitoring & coverage:
    • Observes broker logs, memory usage, crash reports
    • Supports network packet capture for discrepancies

By integrating MQTT protocol module, Penzzer automates detection of issues like:

  • Broker crashes when receiving unexpected stream
  • Mailformed subscription causing out-of-memory
  • Incorrect implementation of session expiry and reconnect behavior
  • Misbehavior on invalid AUTH/ACE flows
  • Incomplete compliance to spec‑enforced flags (e.g., MQTT v5 session behaviors)

MQTT State Machine

The MQTT client/broker interaction follows a well-defined finite-state machine (FSM):

  • Initial (VOID) → on CONNECT → Connected (CONNECTED) → can send/receive PUBLISH, SUBSCRIBE, PINGREQ.
  • On DISCONNECT or network loss → Session Exists (DISCONNECTED)
    • If cleanStart=false and session active, you can reconnect without clearing subscriptions
    • Otherwise, if cleanStart=true, session resets, back to initial state

Fuzz testing each transition is crucial. For instance, sending PUBLISH packets immediately post-VOID state or mixing QoS levels across reconnects can reveal flaws in state tracking and cleanup.

Putting It All Together: Fuzzing MQTT with Penzzer

  1. Import MQTT schema definitions (control packets, fields, types)
  2. Define valid baseline flows: CONNECT → CONNACK → PUBLISH → SUBACK → DISCONNECT
  3. Introduce mutations:
    1. CONNECT: invalid flags, lengths, missing properties
    2. AUTH: invalid PoP tokens, malformed ACE requests
    3. PUBLISH: QoS=3, invalid topic strings
    4. SUBSCRIBE: illegal wildcards, empty topics, duplicate filters
    5. Sequence faults: Publish before CONNECT, multiple CONNECTs
  4. Run Penzzer
  5. Monitor crash logs, behavior anomalies, memory usage, and broker responses
  6. Auto-generate POCs illustrated for developers & links to relevant RFC sections (e.g., v5 user properties, session expiry)

Want to hear more about Penzzer?

Leave your details and we'll reach out shortly.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Don't miss these stories: