Mongoose's built-in TLS 1.3 hostname verification uses the generic mg_match() pattern matcher to compare certificate SAN/CN values against the expected hostname. mg_match() treats * as "match any character except /", which matches dots. Per RFC 6125 Section 6.4.3, a wildcard * in a certificate SAN/CN must only match a single DNS label (no dots). This allows a certificate with SAN *.example.com to incorrectly match hostnames like foo.bar.example.com, and a certificate with SAN *.com to match www.example.com.
This enables man-in-the-middle attacks where an attacker with a wildcard certificate for a parent domain can impersonate any subdomain of arbitrary depth.
static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
const char *server_name,
struct mg_addr *server_ip) {
// ...
while (mg_der_next(&field, &name) > 0) {
if (name.type == 0x87 && name.len == 4) { // IPv4
// ...
} else { // text SAN
if (mg_match(mg_str(server_name),
mg_str_n((char *) name.value, name.len), // cert SAN as pattern
NULL))
return 1; // match
}
}
return -1;
}
static int mg_tls_verify_cert_cn(struct mg_der_tlv *subj, const char *host) {
struct mg_der_tlv v;
int matched = 0;
if (mg_der_find_oid(subj, (uint8_t *) "\x55\x04\x03", 3, &v) > 0) {
matched = mg_match(mg_str(host), mg_str_n((char *) v.value, v.len), NULL);
}
return matched;
}
mg_match() stops * at / but not at . -- in DNS context there are no / characters so * matches across labels.
mg_match("www.example.com", "*.com", NULL) => 1 (WRONG: should be 0)
mg_match("foo.bar.example.com", "*.example.com", NULL) => 1 (WRONG: should be 0)
mg_match("foo.example.com", "*.example.com", NULL) => 1 (correct)
Mongoose's built-in TLS 1.3 hostname verification uses the generic mg_match() pattern matcher to compare certificate SAN/CN values against the expected hostname. mg_match() treats * as "match any character except /", which matches dots. Per RFC 6125 Section 6.4.3, a wildcard * in a certificate SAN/CN must only match a single DNS label (no dots). This allows a certificate with SAN *.example.com to incorrectly match hostnames like foo.bar.example.com, and a certificate with SAN *.com to match www.example.com.
This enables man-in-the-middle attacks where an attacker with a wildcard certificate for a parent domain can impersonate any subdomain of arbitrary depth.
Vulnerable Code
tls_builtin.c:1507-1539 -- SAN verification uses mg_match
tls_builtin.c:1568-1575 -- CN verification also uses mg_match
str.c:71-105 -- mg_match wildcard semantics
mg_match() stops * at / but not at . -- in DNS context there are no / characters so * matches across labels.
Proof of Concept
Compiled test program:
Impact
Verified against cesanta/mongoose master commit 0a3db82.