MQTT Security

MQTT Penetration Testing: A Practical Methodology for Your Own Brokers

A structured, defensive approach to MQTT penetration testing: how to scope a test of your own broker, what to check at each layer and how to turn findings into hardening work.

MQTT penetration testing workflow diagram showing scoping, reconnaissance, authentication and TLS checks against a company-owned broker
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

MQTT penetration testing is a structured way to find weaknesses in your own broker and clients before someone else does. This guide gives you a repeatable methodology, from scoping and reconnaissance to authentication, authorisation, TLS and resource-limit checks, and ends with a hardening checklist you can hand to the team. Everything here is meant for systems you own or have written permission to test.

Rules of Engagement Come First

Testing a broker you do not own is unauthorised access in most jurisdictions, regardless of whether it "was open anyway". Before you send a single packet:

  • Get written authorisation from the system owner, naming hosts, ports, dates and allowed techniques.
  • Define what is out of scope, for example production devices that actuate physical equipment, third-party brokers and public test brokers.
  • Prefer a staging copy. A broker with the same configuration but no live equipment lets you test write access without risk.
  • Agree on stop conditions. If a test causes instability, stop and report.

On a managed service, the provider's acceptable use policy applies too. Test your own tenant's configuration and client behaviour, not the provider's shared infrastructure, and never run load or fuzzing campaigns against a shared cluster or a public broker such as broker.connectmq.com. Its per-client limits exist to keep it usable for everyone.

The Methodology at a Glance

Phase Goal Typical evidence
1. Scoping Know what you are allowed to test Signed scope, asset list
2. Reconnaissance Map listeners, versions and endpoints Port list, TLS details, broker banner
3. Authentication Verify that only valid identities connect Results of anonymous, wrong and reused credential attempts
4. Authorisation Verify each identity is limited to its topics Subscribe/publish matrix per role
5. Transport security Confirm encryption and certificate validation TLS versions, cipher list, client verification behaviour
6. Robustness Check limits and malformed-input handling (staging) Limit responses, broker stability
7. Client review Check devices and apps for secret handling Firmware and config findings
8. Reporting Turn findings into fixes Prioritised remediation list

Phase 2: Reconnaissance of Your Broker

Start by listing every way a client can reach the broker. Teams often secure 8883 carefully and forget a WebSocket listener or an old plain listener.

# List MQTT-related ports on your own host
nmap -Pn -p 1883,8883,8083,8084,9001 your-broker.example.com

# Inspect the TLS endpoint
openssl s_client -connect your-broker.example.com:8883 -servername your-broker.example.com </dev/null

Record for each listener: protocol (TCP, TLS, WS, WSS), whether it is reachable from the internet, the certificate subject and expiry, and which MQTT versions it accepts. If the broker exposes $SYS topics, check what they reveal to an ordinary authenticated client. Version strings and client counts are useful to an attacker and rarely needed by devices.

Phase 3: Authentication Tests

Authentication tests answer one question: can anyone connect who should not? Run each test with an identifier that makes the attempt easy to find in logs.

  1. Anonymous connection. Connect with no username. Expected: refused with a "not authorised" reason.
  2. Wrong password. Expected: refused. Repeat a handful of times and confirm that repeated failures are detected or throttled.
  3. Valid credentials, wrong client ID. If your broker binds client IDs to credentials, a mismatch should be refused.
  4. Duplicate client ID. Connect twice with the same ID and observe session takeover. Make sure your devices handle it, and that an attacker with only a client ID cannot take over a session.
  5. Revoked credentials. Revoke a test identity and confirm it can no longer connect or reconnect.

A small Python script makes these checks repeatable:

import time
import paho.mqtt.client as mqtt

HOST, PORT = "your-broker.example.com", 8883

CASES = [
    ("anonymous", None, None, "pt-anon-01"),
    ("wrong-password", "YOUR_USERNAME", "not-the-password", "YOUR_CLIENT_ID"),
    ("valid", "YOUR_USERNAME", "YOUR_PASSWORD", "YOUR_CLIENT_ID"),
    ("valid-wrong-id", "YOUR_USERNAME", "YOUR_PASSWORD", "pt-other-id"),
]

def try_connect(name, user, pwd, cid):
    result = {}
    client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=cid,
                         protocol=mqtt.MQTTv5)
    client.tls_set()  # verify server certificate with system CAs
    if user:
        client.username_pw_set(user, pwd)

    def on_connect(c, userdata, flags, reason_code, properties):
        result["rc"] = str(reason_code)
        c.disconnect()

    client.on_connect = on_connect
    try:
        client.connect(HOST, PORT, keepalive=10)
        client.loop_start()
        time.sleep(5)  # wait for CONNACK
        client.loop_stop()
    except Exception as exc:
        result["rc"] = f"exception: {exc}"
    print(f"{name:16} -> {result.get('rc', 'no response')}")

for case in CASES:
    try_connect(*case)

Only the valid case should report Success. Everything else should be refused with a clear reason code.

Phase 4: Authorisation Tests

Authentication proves who a client is; authorisation decides what it may do. Build a matrix of roles (sensor, gateway, dashboard, admin service) against topic patterns and test each cell with a real connection.

Role Publish site/+/telemetry Subscribe # Publish site/+/cmd Subscribe $SYS/#
Sensor Allowed (own topic only) Denied Denied Denied
Dashboard Denied Denied (scoped wildcard only) Denied Denied
Control service Denied Denied Allowed Denied

Pay attention to how denials appear. In MQTT 5, a refused subscription returns a SUBACK reason code such as 0x87 (not authorised), and a refused QoS 1 publish returns a PUBACK with a reason code. In MQTT 3.1.1, a denied publish is usually dropped silently, so you must verify with a second, privileged subscriber that the message never arrived. On self-hosted brokers, the MQTT ACL guide explains how to express these rules. Where the broker does not offer per-topic rules, the equivalent control is separate brokers or tenants per trust zone.

Phase 5: Transport Security Tests

Check both sides of TLS:

  • Server side: only modern protocol versions (TLS 1.2 and 1.3), a certificate from a trusted CA that matches the hostname, and no plain listener reachable from the internet.
  • Client side: devices must reject a wrong certificate. Point a test device at a staging host with a self-signed or mismatched certificate and confirm the connection fails. A client that connects anyway is effectively unencrypted against an active attacker.

The MQTT TLS configuration article covers the correct client settings, and analysing MQTT traffic with Wireshark is a good way to prove that payloads are no longer visible on the wire.

Phase 6: Robustness and Limits (Staging Only)

Robustness testing checks how the broker and your clients behave with too much or malformed input. Run it only on a staging broker you control, never on shared or production infrastructure.

  • Oversized payloads: publish a message larger than your configured maximum. Expect a refusal, not a crash.
  • Rate limits: publish faster than your policy allows and confirm the broker throttles or disconnects. On ConnectMQ plans, exceeding a quota is signalled with MQTT 5 reason code 0x97 (quota exceeded), which your clients should handle gracefully.
  • Connection floods: open many connections from one source and check that limits apply per client or per IP.
  • Protocol fuzzing: tools that mutate MQTT packets can reveal parsing bugs. Keep these on an isolated test broker and report crashes to the broker vendor.

For context on designing these limits, see MQTT rate limiting and DoS protection.

Phase 7: Client and Device Review

Many real-world findings live on the device rather than the broker:

  • Credentials hard-coded in firmware or committed to a repository.
  • One shared password for every device in a fleet.
  • Debug topics that publish configuration or secrets.
  • Command topics that execute payloads without validation.
  • TLS verification disabled "to make it work".

Treat every device as potentially extracted and inspected by an attacker. Each one should have unique credentials that can be revoked on their own.

Hardening Checklist From Your Findings

Convert findings into outcomes the team can verify:

  1. Every listener requires authentication; anonymous access exists only where it is intentional and documented.
  2. Only TLS listeners are reachable from the internet, with a valid certificate.
  3. Every device and service has unique, revocable credentials.
  4. Each identity can publish and subscribe only to the topics it needs.
  5. Clients reject invalid certificates.
  6. Message size, rate and connection limits are configured and clients handle refusals.
  7. Repeated failed logins are throttled or blocked.
  8. Broker software is patched on a schedule.
  9. Retained and debug topics contain no secrets.
  10. Retesting is scheduled after major changes.

Several items on this list are handled by the platform when you use a fully managed MQTT service. On ConnectMQ, private brokers require generated credentials, client IDs are bound to those credentials, TLS uses a Let's Encrypt certificate, tenants are isolated, and flood protection plus IP blocking after repeated failed logins are built in. Your test effort can then focus on client behaviour and topic design. The MQTT security best practices article is a good companion for the client-side items.

Test Against a Broker You Control

The safest way to practise this methodology is on a broker you own. Create a private ConnectMQ broker on the free Serverless plan at app.connectmq.com (no credit card), run the authentication and TLS checks against your own credentials, and keep load and fuzzing tests on a local staging broker. For quick, non-sensitive experiments you can still use the free public MQTT broker, within its limits.

Frequently Asked Questions

Can I penetration test a public MQTT broker?

Not without the operator's explicit permission. Public test brokers are shared services, and load or fuzzing tests degrade them for everyone. Test your own brokers or a local staging copy.

What tools are commonly used for MQTT security testing?

Network scanners for listener discovery, openssl s_client for TLS checks, mosquitto_pub and mosquitto_sub for quick tests, and scripted clients such as paho-mqtt for repeatable authentication and authorisation matrices.

How often should we retest our MQTT setup?

After every significant change to listeners, credentials, topic structure or firmware, and on a regular schedule otherwise. Automating the authentication and authorisation checks makes frequent retesting cheap.

What is the most common finding?

Shared or hard-coded credentials on devices and TLS verification disabled on clients are frequent findings, alongside listeners that accept anonymous connections.

Related articles

How to Rotate MQTT Credentials Without Downtime

A step-by-step dual-credential strategy for rotating MQTT usernames and passwords across a fleet: stage the new credential, switch with fallback, verify and only then revoke the old one.

7 min read

Storing MQTT Credentials Securely on Embedded Devices

A practical comparison of ways to protect MQTT usernames and passwords on ESP32 and Linux devices, from encrypted NVS and flash encryption to secure elements and TPM-backed systemd credentials.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.