CWE-297 is the case where a product connects to a host that presents a certificate, but never confirms that the certificate belongs to that host.
MITRE's explanation is worth repeating. A certificate can be well formed, properly signed and chain to a trusted root, and still be a valid certificate for some other site. Encryption to the wrong party protects nothing.
How it happens
The usual bug is a client that checks the signature and skips the name. Mobile apps and client libraries do this when developers replace the default hostname verifier with one that always returns true, often to get past a test environment.
Even when the code does compare names, it can compare badly. MITRE gives an example: an attacker obtains a certificate with a name that begins with a trusted name followed by a NUL byte. A string comparison that stops at the NUL looks only at the trusted part and says yes.
The names to check are the Common Name in the Subject and the Subject Alternative Name extension of an X.509 certificate.
// Vulnerable pattern: a hostname verifier that accepts everything
HttpsURLConnection.setDefaultHostnameVerifier((host, session) -> true);
Real examples
MITRE's observed CVEs from this family include:
- CVE-2012-5810: a mobile banking application does not verify hostname, leading to financial loss.
- CVE-2012-5811: a mobile application for printing documents does not verify hostname, allowing attackers to read sensitive documents.
- CVE-2012-5807: software for electronic checking does not verify hostname, leading to financial loss.
What an attacker gains
Data that the certificate vouches for may not come from the expected system. Trust given to the host on the strength of a malicious certificate can enable spoofing or redirection. MITRE lists impacts on access control and authentication, including gaining the identity of another entity.
How to find it
MITRE describes a direct test: set up an untrusted endpoint that the product will connect to, create a test certificate that uses an invalid hostname but is signed by a trusted CA, and serve it. If the product connects, it has the weakness.
For mobile apps that pin certificates, MITRE points to tools such as Spinner for black box testing of pinning and notes the method may extend to other technologies. Static analysis can also find some cases.
Quick code search terms: custom HostnameVerifier, ALLOW_ALL_HOSTNAME_VERIFIER, check_hostname = False, InsecureSkipVerify.
How to fix it
- Fully check the hostname of the certificate, using the library's built-in verifier, and give the user adequate information about the problem and how to proceed if it fails.
- Compare against the SAN list first, and never use naive string matching on names.
- If you pin certificates, validate all relevant properties, hostname included, before pinning.
- Add a test to CI that serves a right-CA, wrong-name certificate and expects a failure.
# Python: keep both on (these are the defaults)
ctx = ssl.create_default_context()
ctx.check_hostname = True
ctx.verify_mode = ssl.CERT_REQUIRED
Quick check
The certificate is signed by a trusted CA. Why does the name still matter?
Anyone can get a valid certificate for a domain they control. Without a name check, the attacker presents theirs and your client accepts it.