[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.