Like putting the right lock on the wrong front door
Tenable plugin 45411 fires when a TLS service presents a certificate whose identity does not match the hostname the client used. Tenable describes it as the certificate's commonName being for a different machine, but in modern TLS the real check is the certificate identity set — primarily subjectAltName entries, with CN fallback only in older cases. This is not a software-version bug with affected releases; it is a deployment/configuration issue that can affect any HTTPS or TLS service if the bound certificate omits the service's real FQDN, VIP, SANs, wildcard scope, or IP identity.
Tenable's MEDIUM baseline is technically understandable because hostname mismatch undermines endpoint authentication, but in enterprise reality it usually overstates urgency. A mismatch by itself does not give an attacker code execution, privilege escalation, or direct access; it only becomes dangerous if a second condition exists: the client ignores the warning, disables hostname verification, or a custom app implements TLS badly. Modern browsers, standard TLS libraries, HSTS-enabled sites, and most managed clients add a lot of friction here, so this belongs in LOW unless the affected endpoint is customer-facing or paired with clients known to bypass certificate checks.
4 steps from start to impact.
Attacker finds a misbound TLS endpoint
- A TLS-enabled service is reachable
- The certificate bound to the listener does not match the hostname clients use
- Many findings are operational noise from scanning by IP, backend node name, or alternate DNS alias rather than the intended public FQDN
- A mismatch alone does not create attacker access
Client validation blocks the connection
- A user or application connects using the mismatched hostname
- The client performs normal certificate validation
- Modern browsers and standard HTTP/TLS stacks usually stop here
- HSTS sites tighten the failure mode by preventing easy click-through in browsers
Attacker needs a second failure: trust bypass or broken client
mitmproxy, Burp, or another interception proxy, but the attack only works if the victim app/browser proceeds anyway or has hostname verification disabled.- Attacker has man-in-the-middle position or can redirect traffic
- Victim client accepts mismatched hostnames or the user bypasses warnings
- Requires prior network foothold or traffic redirection
- Requires user override, broken mobile app, custom
HostnameVerifier, or similar client weakness
Impact stays in the lane of spoofing and trust erosion
- The victim proceeds past the certificate error or uses a broken client
- Sensitive traffic crosses the affected connection
- No privilege gain or remote code execution from the server-side condition itself
- Blast radius is limited to clients and workflows that actually trust the bad endpoint
45411 itself.The supporting signals.
| In-the-wild status | No known KEV-style exploitation signal. This is a misconfiguration class, not a named CVE with active exploitation tracking. |
|---|---|
| Proof-of-concept availability | Trivial to demonstrate, not really a PoC vuln. badssl exposes wrong.host.badssl.com, and interception tools like mitmproxy/Burp can validate whether clients incorrectly accept mismatched names. |
| EPSS | N/A. EPSS scores CVEs; plugin 45411 is a Nessus detection for a certificate-name mismatch, not a CVE. |
| KEV status | Not applicable. CISA KEV entries require a CVE and evidence of exploitation; this finding is neither. |
| Vendor score and vector | Tenable: MEDIUM / 5.3 with CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N. That vector assumes integrity impact in the abstract, but it ignores the real-world need for client override or broken hostname verification. |
| Affected scope | Any TLS service whose presented certificate identity does not match the hostname clients use. This commonly shows up on load balancers, reverse proxies, default appliance certs, internal admin ports, and IP-based scans. |
| Fixed state | No patched software version. The fix is to reissue/rebind a certificate with the correct SANs/wildcard/VIP names, or to scan the service using the hostname it is actually designed to serve. |
| Scanning and exposure reality | High scanner visibility, low exploit specificity. Internet-wide exposure counts are not very meaningful because the same endpoint may be fine on its intended FQDN and only fail when queried by IP or an alternate alias. |
| Disclosure and provenance | Published by Tenable on 2010-04-03; updated 2020-04-27. This is scanner logic for TLS identity validation, not a vendor-reported product bug attributed to a researcher. |
noisgate verdict.
The decisive factor is that this finding usually requires a second failure on the client side — warning bypass, disabled hostname verification, or a buggy custom TLS implementation — before it becomes exploitable. In standard enterprise fleets, modern browsers and libraries stop the connection, so the finding is primarily trust hygiene unless the endpoint is public-facing and user workflows are known to hit it.
Why this verdict
- Requires a second failure: the certificate mismatch alone is not enough; the attacker still needs client click-through, disabled hostname checks, or a custom app that trusts the wrong host.
- Attacker position is post-routing, not just remote reachability: practical abuse usually implies MITM capability, DNS manipulation, proxy insertion, or some other traffic-control position rather than simple internet access.
- Exposure population is narrower than the plugin suggests: many
45411hits are artifacts of scanning by IP, backend node name, or alternate alias, while real users only ever connect through the correct FQDN.
Why not higher?
This is not a server compromise primitive. There is no built-in RCE, auth bypass, or privilege escalation path, and modern clients usually reject the session before any sensitive operation happens. Without evidence that production clients suppress hostname verification, the blast radius stays limited.
Why not lower?
It is still a real trust failure, not pure noise. If the endpoint is customer-facing, used by thick clients, or tied to mobile/custom apps that relax TLS checks, the mismatch can enable spoofing or interception of real traffic. It also conditions operators and users to normalize certificate warnings, which is bad security debt.
What to do — in priority order.
- Validate the intended service name — First confirm whether the scan used the hostname the service is actually meant to present. If the finding only appears when scanning by IP or backend node alias, document and suppress that path; for a LOW verdict there is no SLA — treat as backlog hygiene.
- Rebind a certificate with correct SANs — Where the mismatch is real, issue a certificate that includes the exact FQDNs, VIP names, wildcard scope, or IP SANs actually used by clients, then bind it on the listener. For LOW, fold this into the next planned certificate maintenance window rather than treating it like an emergency patch.
- Test client behavior against wrong-host certs — Use
badssl,mitmproxy, orBurpto prove whether managed browsers, agents, mobile apps, and internal tooling reject mismatched names. This is the fastest way to separate harmless config drift from a genuine interception risk in your environment. - Enforce strict TLS handling in custom apps — Review internal code for disabled hostname verification, permissive
HostnameVerifierlogic, trust-all cert handlers, or silent click-through behavior. If those clients exist, fix them with priority because they are the real amplifier that turns this finding into exploitable risk.
- Trusting the issuing CA alone doesn't solve this; a valid chain for the *wrong* hostname is still the wrong certificate.
HSTShelps browsers refuse bad cert paths more strictly, but it does not correct a mismatched certificate on the server.- Network segmentation by itself doesn't remove the risk if internal users or apps still connect to the service name that mismatches and then bypass warnings.
Crowdsourced verification payload.
Run this from an auditor workstation or the scanner host that can reach the target TCP port; no root is required, only openssl. Invoke it as ./check_cert_hostname.sh <connect_host> <port> <expected_hostname> — for example: ./check_cert_hostname.sh 10.20.30.40 443 app.example.com.
#!/usr/bin/env bash
# check_cert_hostname.sh
# Verifies whether a TLS service presents a certificate matching the expected hostname.
# Exit codes:
# 0 = PATCHED (hostname matches certificate)
# 1 = VULNERABLE (hostname mismatch)
# 2 = UNKNOWN (network/openssl/parsing issue)
set -u
CONNECT_HOST="${1:-}"
PORT="${2:-}"
EXPECTED_HOST="${3:-}"
if [[ -z "$CONNECT_HOST" || -z "$PORT" || -z "$EXPECTED_HOST" ]]; then
echo "UNKNOWN - usage: $0 <connect_host> <port> <expected_hostname>"
exit 2
fi
if ! command -v openssl >/dev/null 2>&1; then
echo "UNKNOWN - openssl not found"
exit 2
fi
match_dns() {
local pattern="$1"
local host="$2"
pattern="${pattern,,}"
host="${host,,}"
# Exact match
if [[ "$pattern" == "$host" ]]; then
return 0
fi
# Simple wildcard support for left-most label only, e.g. *.example.com
if [[ "$pattern" == \*.* ]]; then
local suffix="${pattern#*.}"
if [[ "$host" == *".$suffix" ]]; then
local left="${host%.${suffix}}"
# Must replace exactly one label, not multiple levels or empty
if [[ "$left" != "$host" && "$left" != *.* && -n "$left" ]]; then
return 0
fi
fi
fi
return 1
}
TMP_CERT="$(mktemp)"
cleanup() {
rm -f "$TMP_CERT"
}
trap cleanup EXIT
# Pull the leaf certificate.
if ! timeout 15 bash -c "echo | openssl s_client -connect '${CONNECT_HOST}:${PORT}' -servername '${EXPECTED_HOST}' -showcerts 2>/dev/null" \
| awk 'BEGIN{in_cert=0} /-----BEGIN CERTIFICATE-----/{in_cert=1} in_cert{print} /-----END CERTIFICATE-----/{exit}' > "$TMP_CERT"; then
echo "UNKNOWN - failed to connect or retrieve certificate"
exit 2
fi
if ! grep -q "BEGIN CERTIFICATE" "$TMP_CERT"; then
echo "UNKNOWN - no certificate returned"
exit 2
fi
CERT_TEXT="$(openssl x509 -in "$TMP_CERT" -noout -text 2>/dev/null)"
if [[ -z "$CERT_TEXT" ]]; then
echo "UNKNOWN - unable to parse certificate"
exit 2
fi
EXPECTED_LC="${EXPECTED_HOST,,}"
MATCHED=1
SAN_FOUND=0
# Prefer SANs when present.
while IFS= read -r san; do
SAN_FOUND=1
san="${san#DNS:}"
san="${san#IP Address:}"
san="${san// /}"
if match_dns "$san" "$EXPECTED_LC"; then
MATCHED=0
break
fi
done < <(printf '%s
' "$CERT_TEXT" | awk '
/Subject Alternative Name/ {getline; gsub(/, /, "\n"); print; next}
' | tr -d '\r' | grep -E '^(DNS:|IP Address:)')
# Fallback to CN only if no SANs were found.
if [[ $MATCHED -ne 0 && $SAN_FOUND -eq 0 ]]; then
CN="$(printf '%s
' "$CERT_TEXT" | sed -n 's#.*Subject:.*CN[[:space:]]*=[[:space:]]*\([^,/]*\).*#\1#p' | head -n1 | xargs)"
if [[ -n "$CN" ]] && match_dns "$CN" "$EXPECTED_LC"; then
MATCHED=0
fi
fi
if [[ $MATCHED -eq 0 ]]; then
echo "PATCHED - certificate matches expected hostname '${EXPECTED_HOST}'"
exit 0
else
echo "VULNERABLE - certificate does not match expected hostname '${EXPECTED_HOST}'"
exit 1
fi
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.