curl · Report #2764830
CVE-2024-9681: HSTS subdomain overwrites parent cache entry
How it was found
Summary:
Suppose my HSTS cache file has the following content:
.domain.com "20241107 01:02:03"
.sub.domain.com "unlimited"
Now, I connect to https://sub.domain.com/. Suppose this domain now sets a HSTS policy: Strict-Transport-Security: max-age=15768000 ; includeSubDomains. Surprisingly my HSTS cache file now becomes:
.domain.com "unlimited"
.sub.domain.com "20250408 00:26:19"
While the HSTS policy for "sub.domain.com" is correctly updated, the HSTS expiration time for "domain.com" is mistakenly set to be the previous expiration time for "sub.domain.com".
If I have multiple levels of subdomains in my HSTS cache, the situation is more confusing. Suppose my HSTS cache is:
.com "20241108 01:02:03"
.badssl.com "20260408 04:39:00"
Now I connect to https://hsts.badssl.com/index.html. After that, the HSTS cache becomes:
.com "20260408 04:39:00"
.hsts.badssl.com "20250408 04:49:30"
Steps To Reproduce:
-
curl version: curl 8.11.0-DEV (x86_64-pc-linux-gnu) libcurl/8.11.0-DEV OpenSSL/3.0.2 libpsl/0.21.0, curl source HEAD commit: 86d5c2651d3ea8af316eff2a2452ae61413c66ba
-
Also reproducible in curl 8.10.1 release version.
- Create a text file
testhsts.txtwith the following content:.badssl.com "20241101 00:25:31"(less than 1 month expiration time) - Run
curl -v --hsts ./testhsts.txt "http://hsts.badssl.com/index.html". Check the content oftesthsts.txt - Run
curl -v --hsts ./testhsts.txt "http://hsts.badssl.com/index.html"again. Check the content oftesthsts.txtagain.
- Create a text file
-
After step 2, the content of
testhsts.txtis:
.badssl.com "20241101 00:25:31"
.hsts.badssl.com "20250408 04:39:00"
- After step 3, the content of
testhsts.txtis:
.badssl.com "20250408 04:39:00"
.hsts.badssl.com "20250408 04:40:01"
You can see the expiration time of .badssl.com is set incorrectly.
Supporting Material/References:
None
Impact
For shared subdomains, i.e. different subdomains are controlled by different users, a malicious subdomain can influence the HSTS expiration time of the parent domain. By my tests, a subdomain can only increase the expiration time of its parent domain, but can't shorten it. A malicious subdomain can cause a denial of service of its parent domain, if the parent domain only plans to support HSTS for a short period of time, and wants to revert to plaintext http after a while. By exploiting this bug, the malicious subdomain can set a very long max-age for itself, and this bug can cause curl to overwrite the parent domain's HSTS expiration time to be very long.