NS-077
documentedconnection-named-differently-from-the-request
Overriding the Host header leaves the TLS handshake pointing somewhere else
- reads as
- `curl -H 'Host: app.example.com' https://<origin-ip>/` returns 200 with a plausible page. Conclusion drawn: the origin serves app.example.com correctly.
- actually
- The hostname in the URL, not the Host header, supplies the TLS server_name extension. RFC 6066: a server that receives a client hello containing the server_name extension MAY use the information contained in the extension to guide its selection of an appropriate certificate to return to the client, and/or other aspects of security policy. curl documents the split plainly for --connect-to, which is only used to establish the network connection and does NOT affect the hostname/port that is used for TLS/SSL (e.g. SNI, certificate verification). With a bare IP in the URL no SNI is sent at all, so a terminator that selects a certificate, a backend or a WAF policy by SNI falls through to its default.
- blind because
- The 200 is real and the body may well be the right site, because the default virtual host is often the site under test. Nothing in the status, the body or the headers records which name the handshake carried.
- the check
- Keep the hostname in the URL and move only the address: `curl -sk --resolve app.example.com:443:<ip> https://app.example.com/`. Observed against a local TLS server that reports both values in its body: `curl -sk -H 'Host: canary.example' https://127.0.0.1:8443/` returned `SNI=None HOST=canary.example`, while `curl -sk --resolve canary.example:8443:127.0.0.1 https://canary.example:8443/` returned `SNI=canary.example HOST=canary.example:8443`. `openssl s_client` split the same way: no -servername, no SNI.
- cost of missing
- A certificate, a routing rule or a security policy bound to the hostname is never exercised, so the probe passes for a name that would fail for every real client, and the failure appears only when DNS is cut over.
- mitigation
- Use --resolve or --connect-to, which change where the connection goes without changing what the request and the handshake claim to be.
- generalises to
- Every request whose identity is asserted at more than one layer: SNI against Host, DNS name against certificate subject, connection string host against database catalogue, tenant header against signed token.
- source
- rfc-editor.org