HexBrain

curl · Report #3531216

MQTT Protocol Packet Injection via Unchecked CONNACK Remaining Length

Informativestatus
lowseverity
45upvotes
5 Feb 2026disclosed

How it was found

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.

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

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original