Currently, (*x509.Certificate).VerifyHostname loops over all DNS SAN
entries. For each entry, it calls matchHostnames, which calls
strings.Split(host, ".") on the same input hostname every time.
With a large subjectAltName DNS list, this makes verification cost scale
with:
- number of DNS SAN entries in the certificate, times
- size/label-count of the hostname being verified.
This cost is paid even when the certificate is otherwise untrusted,
because x509.Verify performs hostname verification before chain
building.
This is primarily client-side in TLS, and also affects any application
directly calling VerifyHostname or x509.Verify with
VerifyOptions.DNSName.
Two relevant hostname cases:
- DNS-valid hostnames have strict limits (total length about 253 bytes,
label length <= 63). A long-but-valid hostname near the DNS maximum
still noticeably amplifies the per-SAN work.
- If an application passes an attacker-controlled hostname string
without enforcing DNS limits, Go will accept very long, many-label
inputs as "valid" and perform much more work.
Thanks to Jakub Ciolek jakub@ciolek.dev for reporting this issue.
Currently, (*x509.Certificate).VerifyHostname loops over all DNS SAN
entries. For each entry, it calls matchHostnames, which calls
strings.Split(host, ".") on the same input hostname every time.
With a large subjectAltName DNS list, this makes verification cost scale
with:
This cost is paid even when the certificate is otherwise untrusted,
because x509.Verify performs hostname verification before chain
building.
This is primarily client-side in TLS, and also affects any application
directly calling VerifyHostname or x509.Verify with
VerifyOptions.DNSName.
Two relevant hostname cases:
label length <= 63). A long-but-valid hostname near the DNS maximum
still noticeably amplifies the per-SAN work.
without enforcing DNS limits, Go will accept very long, many-label
inputs as "valid" and perform much more work.
Thanks to Jakub Ciolek jakub@ciolek.dev for reporting this issue.