The recent vulnerability CVE-2024-9681 in cURL reveals a subtle but significant issue with how the popular command-line tool and its library handle HSTS (HTTP Strict Transport Security) for domains and their subdomains. If your application or project uses cURL with HSTS enabled, and you ever work with both parent and subdomain URLs, this bug might expose your users to more or less HSTS protection than you or a server intended — without you even realizing it.

In this deep-dive, we’ll break down what’s really happening, provide some code snippets to help you see the issue in action, and share resources for more information and fixes. We'll keep it straightforward so you don’t need to be a cURL or security expert to understand this issue.

What is HSTS and How Does cURL Use It?

HSTS is a web security policy mechanism that tells browsers or clients to always use HTTPS instead of HTTP for that host, for a specified period. If a domain responds with a header like:

Strict-Transport-Security: max-age=31536000

the client will “remember” to use HTTPS for one year, even if a user or program requests HTTP.

cURL (since version 7.74.) supports HSTS, storing this data in a local cache file when enabled with the --hsts option or the corresponding libcurl mechanisms.

The Problem

When cURL is asked to use HSTS and both a *subdomain* (like x.example.com) and its *parent* (example.com) have entries in the HSTS cache, an expiry time received from the subdomain might overwrite the parent domain’s HSTS cache entry by mistake! This causes the parent’s "force HTTPS" rule to expire sooner (or later) than the true value the server wanted.

cURL adds or updates this in the HSTS cache.

2. You (or your app) previously accessed (or manually added) example.com with an HSTS setting for a different period, e.g., max-age=360 (one hour).

3. Due to the bug, when HSTS for x.example.com expires and is cleaned, cURL’s cache update logic *accidentally* overwrites the parent’s expiry with the child's value.

This means

- http://example.com requests might force HTTPS for too little or too long.

Cache File before Bug

example.com  HSTS  max-age=360  # Valid for 1 hour
x.example.com HSTS max-age=600   # Valid for 10 minutes

Triggering Conditions

- The HSTS cache must already have entries for both the parent and subdomain (populated by previous transfers or manual edit).

Example Usage in Code

# Enable HSTS in cURL and store the cache
curl --hsts hsts-cache.txt https://x.example.com
curl --hsts hsts-cache.txt https://example.com

# Now fetch HTTP URLs
curl --hsts hsts-cache.txt http://x.example.com
curl --hsts hsts-cache.txt http://example.com

Demonstration of the Issue in libcurl (pseudocode)

// Assume hsts_cache is a map: domain -> expiry
update_hsts("x.example.com", expiry=600);
// [BUG] Under some conditions, update_hsts for the subdomain can also change
// hsts_cache["example.com"] expiry!
assert(hsts_cache["example.com"] == 600); // Should have been 360!

Exploit Details: What Attackers (or Accidents) Can Do

- If you can control an HSTS header from any subdomain (like sharing hosting or misconfigured headers), you could intentionally force the parent domain’s HSTS cache entry to expire early.

This could Remove HTTPS enforcement for example.com earlier than planned.

- Conversely, you could “extend” the HTTPS-only policy for the parent, potentially breaking communication if the parent stops supporting HTTPS.

The bug cannot be trivially exploited for remote code execution or data exfiltration on its own, but it can reduce or break HSTS security guarantees.

Upgrade to a patched version of cURL

- Official cURL downloads and news

Original References

- cURL Security Advisory for CVE-2024-9681
- NVD Entry for CVE-2024-9681
- cURL HSTS Documentation

Summary

CVE-2024-9681 is a niche but important bug: when cURL stores HSTS details for both subdomains and their parent domains, a subdomain’s expiry might overwrite the parent’s, creating a window where HTTPS enforcement is too strong or too weak. For anyone managing the security of applications using cURL, update your tools, check your caches, and review affected infrastructures. Stay alert for HSTS’s subtle edge cases!

If you found this post useful, share it with your sysadmin or DevOps teams and don’t forget to keep your cURL up to date!

Timeline

Published on: 11/06/2024 08:15:03 UTC
Last modified on: 12/13/2024 14:15:22 UTC