MQTT over TLS Analysis
practicalMQTT over TLS Analysis
Beaucoup d'opérateurs pensent que basculer MQTT sur le port 8883 (TLS) suffit à sécuriser leur flotte. C'est faux. Une mauvaise validation de certificat, un CA auto-signé largement distribué, ou un client mobile qui accepte n'importe quoi transforme TLS en théâtre.
Avertissement légal : ces techniques ne doivent être appliquées que sur vos propres infrastructures ou dans le cadre d'un mandat de test d'intrusion signé.
Connexion TLS propre
# Vérification stricte CA + hostname
mosquitto_sub -h broker.cible.tld -p 8883 \
--cafile /etc/ssl/certs/ca-certificates.crt \
-t '#' -v
# Mutual TLS : le client présente aussi un certificat
mosquitto_sub -h broker.cible.tld -p 8883 \
--cafile ca.crt --cert client.crt --key client.key \
-t 'home/+/temp' -v
Si la connexion échoue, lancez openssl s_client :
openssl s_client -connect broker.cible.tld:8883 -showcerts </dev/null
Notez le CN, le SAN, l'émetteur. CN = localhost, mqtt, ou IP interne ? Première trouvaille : certificat non adapté.
Détection de validation laxiste
Le bug classique : un client (firmware ESP32, app mobile, gateway industrielle) accepte n'importe quel certificat.
# Générez un CA et un cert serveur en 30 secondes
openssl req -new -x509 -days 365 -nodes -out ca.crt -keyout ca.key \
-subj "/CN=FakeCA"
openssl req -new -nodes -out server.csr -keyout server.key \
-subj "/CN=broker.cible.tld"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 365
# Lancez mosquitto en TLS sur 8883
cat > rogue.conf <<'EOF'
listener 8883
cafile ca.crt
certfile server.crt
keyfile server.key
require_certificate false
allow_anonymous true
EOF
mosquitto -c rogue.conf -v
Redirigez le trafic du device (ARP spoof, DNS poisoning, DHCP en lab). Si le device publie chez vous, la validation TLS est inexistante.
Interception avec mitmproxy
# Extrayez le CA bundle du firmware
binwalk -e firmware.bin
grep -rE "BEGIN CERTIFICATE" _firmware.bin.extracted/
# Si le CA est court, vérifiez s'il est public ou custom
openssl x509 -in extracted_ca.pem -text -noout | grep -E "Issuer|Subject"
Si le firmware embarque un CA custom et que vous récupérez sa clé privée (cas réel — vendors distribuant la même paire à tous les clients), vous signez votre propre cert serveur et l'interception devient triviale.
Inspection Wireshark
# Filtre Wireshark utile
tls.handshake.type == 1 and tcp.port == 8883
Le SNI révèle le hostname réel du broker même si le device utilise une IP. Combiné avec la taille des messages chiffrés, vous devinez les patterns (un message de 47 octets toutes les 30s = keepalive avec température).
Script Python : test de connexion TLS faible
import paho.mqtt.client as mqtt
import ssl
def test_broker(host, port=8883):
client = mqtt.Client()
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
client.tls_set_context(ctx)
try:
client.connect(host, port, 5)
client.loop_start()
return "ACCEPTE TLS sans validation"
except Exception as e:
return f"refuse: {e}"
finally:
client.disconnect()
for h in ["broker1.tld", "broker2.tld"]:
print(h, "->", test_broker(h))
Checklist de findings
- Certificat avec CN incorrect ou expiré
- TLS 1.0 / 1.1 activé sur 8883
require_certificate falsecôté broker- CA partagé entre tous les déploiements du fabricant
- Clients qui ignorent
verify_mode - Port 1883 (non chiffré) toujours ouvert en parallèle