Skip to content

[Eclipse Paho] Protocol compliance issue in Eclipse Paho MQTT Go client (Remaining Length encoding)

From the security mailing list:


I would like to report a potential protocol-compliance issue in the Eclipse Paho Go MQTT v3.1.1 client (paho.mqtt.golang).

This issue is likely a low-severity or borderline case, but because it may affect interoperability with non-compliant brokers, I am submitting it through the security contact.

Summary

In Eclipse Paho Go MQTT v3.1.1 (paho.mqtt.golang) versions ≤ 1.5.1, the library may generate MQTT packets with an invalid Remaining Length field when the payload size exceeds the MQTT-specified maximum of 2²⁸−1 bytes.

This results in a Remaining Length encoded in 5 or more bytes, which violates the MQTT v3.1.1 specification.

Impact

All MQTT-compliant brokers will reject such packets and close the connection immediately. However, brokers with an incorrect implementation of Remaining Length decoding (for example, integer overflow in the multiplier logic) may parse the malformed packet incorrectly.

In such cases, a single oversized PUBLISH packet sent by the client may be interpreted by the broker as multiple MQTT control packets fully influenced by attacker-controlled payload data. This can cause the broker’s state machine to advance in unintended ways or process synthetic control packets that the client never intended to send.

This behavior does not compromise the Eclipse Paho client itself, but it can serve as a packet-smuggling primitive when interacting with a broker that mishandles Remaining Length calculations.

Reproduction

To reproduce the out-of-spec encoding, publish a payload larger than 2²⁸−1 bytes.

For example:

message := make(byte[], 1<<32) // exceeds MQTT max length
client.Publish("test/", 0, false, message)

Technical Cause

The client does not validate that the payload size is below the MQTT maximum before calling encodeLength().

The relevant code is located in: https://github.com/eclipse-paho/paho.mqtt.golang/blob/b30523793968e6b7a7b1f76338a58c4fe9755299/packets/packets.go#L343

Attack Requirements / Conditions

This becomes a potential security issue only if all of the following conditions are met:

  • The application receives attacker-controlled or partially attacker-controlled message bodies.
  • The attacker can provide more than 2²⁸−1 bytes of data.
  • The broker incorrectly decodes the Remaining Length field and is susceptible to integer overflow, such as:
multiplier := uint32(1)
value := uint32(0)
for i := 0; ; i++ {
    value += (buf[i] & 0x7f) * multiplier
    multiplier *= 128 // possible overflow to 0
    if (buf[i] & 0x80) == 0 {
        return value
    }
}

If multiplier overflows to zero, the broker may misinterpret the packet length.

Notes

Because this requires a non-compliant broker to become exploitable, this issue may be considered a correctness bug rather than a vulnerability.

I will defer the classification to your security team. I can provide additional details, proof-of-concept, or examples of affected broker implementations upon request.

Edited by Lukas Pühringer
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information