CVE-2023-28321 - Curl Improper Certificate Validation and the Wildcard Wild West
Curl is a household name for anyone who deals with data transfers over the internet—be it downloading a file, querying APIs, or running tests. Secure connections are vital for such tasks, which is why curl’s security mechanisms matter so much. But in early 2023, a sneaky bug in the way curl validated “wildcards” in TLS certificates opened doors for attackers to impersonate websites, especially when International Domain Names (IDN) were used. This is known as CVE-2023-28321, and in today’s post, we’ll break down how it happened, what makes it dangerous, and how you can see it for yourself.
What is CVE-2023-28321?
An improper certificate validation vulnerability affecting curl versions before 8.1.. The bug lies in curl’s “private” name matching function, used optionally (when not delegating the task to a TLS library like OpenSSL), which didn’t properly handle “wildcard” (*) patterns when verifying TLS certificates with internationalized hostnames (IDN).
Main issue:
IDNs are converted into “punycode,” which always begin with the prefix xn--.
- The wildcard handling code in curl allowed patterns like x* to match these xn-- prefixes, even though there was nothing remotely like an “x” in the original hostname.
This meant a site with a TLS certificate for x*.example.com could potentially pass validation for an IDN like xn--something.example.com, even if it shouldn’t.
They could then set up a malicious domain such as xn--legitbnk-yza.com.
- When a user with the vulnerable version of curl connects to this malicious server—expecting the legitimate IDN—they’d see no validation error, and sensitive data could be leaked.
In effect, improper wildcard matching could allow attackers to impersonate legitimate international domains and intercept (or modify) secure traffic.
What Is “Punycode” and Why Does It Matter?
International Domain Names (IDN) let users register domains in many languages and scripts, but underlying standards (DNS) only allow ASCII. Punycode is the encoding that lets this work:
All punycodes start with xn--.
Certificate checks (per RFC 6125 section 7.2) are supposed to compare the ASCII (punycode) version, not the Unicode label. And wildcards should never be allowed to match the fixed xn-- part!
Here’s a simplified (pseudo-)code snippet of what curl’s wildcard function looked like
/* simplified example */
int wildcard_match(const char *pattern, const char *hostname) {
while (*pattern && *hostname) {
if (*pattern == '*') {
// try to match or more chars
pattern++;
while (*hostname) {
if (wildcard_match(pattern, hostname++))
return 1;
}
return ;
}
if (*pattern != *hostname) return ;
pattern++;
hostname++;
}
return !*pattern && !*hostname;
}
If the pattern is x*, and the hostname is xn--something, the match passes.
- But if the pattern were x* and the original (Unicode) name was say, “αβγ.com,” it still passes, since “αβγ.com” would become xn--mxaf.com.
This is wrong, because the wildcard must NOT match the fixed xn-- part!
User visits IDN:
Victim’s curl (pre-8.1., not using system TLS matching) connects to what it thinks is a trusted domain.
Here is a demo of how the matching fails (Python-ish for readability)
def wildcard_match(pattern, hostname):
if pattern == "x*":
# This matches any string that starts with 'x'
return hostname.startswith("x")
return False
puny_host = "xn--badsite-u9a.com"
if wildcard_match("x*", puny_host):
print("TLS cert accepted for: %s" % puny_host)
else:
print("TLS cert rejected!")
# Output: TLS cert accepted for: xn--badsite-u9a.com
Even though the real name is unrelated to “x,” the validation passes because of the punycode prefix.
Upgrade curl!
This is fixed as of curl v8.1., so grab the latest version immediately.
Check your build:
If you use a distro’s curl, see if it’s built to rely on system TLS matchers (like OpenSSL, GnuTLS, etc.)—those don’t have this bug.
Prevent wildcard shenanigans:
CAs should not issue wildcards like x*.domain.com to begin with! Use Certificate Transparency logs to check what certs are being issued for your domains.
References and More Reading
- CVE-2023-28321 Official Advisory
- NVD Entry for CVE-2023-28321
- curl GitHub PR/commit fixing the bug
- RFC 6125: Wildcard Certs and IDN
- Everything curl: Name matching
Summary
CVE-2023-28321 is a sneaky flaw rooted in how curl handles wildcard patterns and IDN certificates, allowing certain malicious combinations to slip past validation. Always upgrade to the latest version, audit your dependencies, and remember: security is built on the tiniest details.
If you learn something new or found this post helpful, share it with your friends and network—vulnerabilities like these are easier to miss but can be disastrous if left unchecked.
Timeline
Published on: 05/26/2023 21:15:00 UTC
Last modified on: 06/16/2023 19:17:00 UTC