So it is feasible -- at scale -- for TLS clients to validate that DNS names in the SNI extension really are DNS names, and are not IP addresses or bits of URL.
Was Windows' Schannel also tested? Or this is simply due to the dev team having access to Linux and macOS?
Currently, the only server names supported are DNS hostnames; however, this does not imply any dependency of TLS on DNS, and other name types may be added in the future (by an RFC that updates this document).
RFC 5280:
The subject alternative name extension allows identities to be bound to the subject of the certificate. These identities may be included in addition to or in place of the identity in the subject field of the certificate. Defined options include an Internet electronic mail address, a DNS name, an IP address, and a Uniform Resource Identifier (URI). Other options exist, including completely local definitions.
However, this doesn't cover DNS name validation for the hostname:
"This specification does not mandate a particular registered name lookup technology and therefore does not restrict the syntax of reg-name beyond what is necessary for interoperability"
It also doesn't constrain the userinfo ("username:password") part described in this vulnerability.
So yeah, it's non-trivial.
authority = [ userinfo "@" ] host [ ":" port ]
described in section 3.2 of that specification. Looks pretty trivial to me.The RFC reads:
> Use of the format "user:password" in the userinfo field is deprecated.
In the real world, for HTTP use cases, you can't just ignore this because it's deprecated.
Yes. So, a correct implementation can't use this document to destructure it, but that's OK because it doesn't need to do so. It can however easily distinguish the userinfo from the rest of the authority.
Unless, like this code, it simply doesn't bother to try.
> In the real world, for HTTP use cases, you can't just ignore this because it's deprecated.
Then I guess you'll need to write code to further parse the userinfo. Seems pretty easy, but this document doesn't explain how because it's deprecated. No impact on whether you can find the host name in the authority since that's a separate field from userinfo.
Assuming, of course, that you bother to separate userinfo from the domain name in the authority, which Lynx did not.
From [0], the issue arises when they send "user:pass@host" to SSL_set_tlsext_host_name, which happily sets the SNI to whatever it's given [1]. As a point of comparison, when you create a Rustls client via ClientSession::new [2], you have to pass it a DNSNameRef, which will validate that there's no auth component in the string it wraps, and return an error if you try to set the server name to something involving auth details.
I'm sure there's reasons why OpenSSL is set up to work like this, but I can't see why anyone would ever want to send those auth details in the clear in the SNI, and I wish it provided an API that would anticipate this misuse, like in Rust. The OpenSSL docs don't indicate it's an issue you should think about when invoking this function [3].
I realise I'm picking on OpenSSL here, and GnuTLS appears to do the exact same thing. I'm just not certain anyone not wearing a hazmat suit and being watched by multiple other trained professionals should be handling OpenSSL code.
0: https://www.openwall.com/lists/oss-security/2021/08/07/7
1: https://github.com/openssl/openssl/blob/5cbd2ea3f94aa8adec9b...
2: https://docs.rs/rustls/0.19.1/rustls/struct.ClientSession.ht...
3: https://www.openssl.org/docs/man1.1.1/man3/SSL_set_tlsext_ho...