MQTT Protocol Packet Injection via Unchecked CONNACK Remaining Length
Low
Vulnerability Details
I'm not sure if this is a vulnerability or intended behavior, but I noticed that curl MQTT implementation accepts CONNACK packets with Remaining Length values greater than 2, which appears to violate the MQTT v3.1.1 specification.
According to the MQTT spec, CONNACK packets should have a Remaining Length of exactly 2 bytes, but curl seems to process packets with larger values and treats the extra bytes as new MQTT messages.
- https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd01/mqtt-v3.1.1-csprd01.html#_Toc376954333
## Affected version
```
» curl -V
curl 8.18.0 (x86_64-pc-linux-gnu) libcurl/8.18.0 OpenSSL/3.6.1 zlib/1.3.1 brotli/1.2.0 zstd/1.5.7 libidn2/2.3.8 libpsl/0.21.5 libssh2/1.11.1 nghttp2/1.68.0 ngtcp2/1.20.0 nghttp3/1.15.0 mit-krb5/1.21.3
Release-Date: 2026-01-07
Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd
```
## Steps To Reproduce:
1. So in [mqtt_verify_connack](https://github.com/curl/curl/blob/master/lib/mqtt.c#L402) its reads the entire CONNACK packet,but only validates and consumes the first 2 bytes of the payload.
```
static CURLcode mqtt_verify_connack(struct Curl_easy *data)
{
...
result = mqtt_recv_atleast(data, MQTT_CONNACK_LEN);
if(result)
goto fail;
...
if(ptr[0] != 0x00 || ptr[1] != 0x00) { // only checks first 2 bytes:
...
}
mqtt_recv_consume(data, MQTT_CONNACK_LEN);
...
}
```
1. And in [mqtt_doing](https://github.com/curl/curl/blob/1acf0c45f4ede462a553353d774395b68614a42a/lib/mqtt.c#L901) its reads from the buffer for the next MQTT message, but the leftover bytes are still in the buffer.
```
case MQTT_CONNACK:
result = mqtt_verify_connack(data);
...
mqtt->nextstate = MQTT_FIRST;
```
1. I made a simple python poc script that will mimic MQTT, run this and try with curl to the server and its works to do inject a PUBLISH command.
{F5294478}
So bytes embedded inside CONNACK are reinterpreted as a separate MQTT message, and from this attacker can inject arbitrary MQTT messages.
## Supporting Material/References:
I attached the poc.py script and screenshoot bellow.
## Impact
An attacker could potentially inject other control packets.
Actions
View on HackerOneReport Stats
- Report ID: 3531216
- State: Closed
- Substate: informative
- Upvotes: 16