[HN Gopher] Connection reuse may route traffic to malicious servers
___________________________________________________________________
Connection reuse may route traffic to malicious servers
Author : pabs3
Score : 49 points
Date : 2022-05-27 08:29 UTC (14 hours ago)
(HTM) web link (bugzilla.mozilla.org)
(TXT) w3m dump (bugzilla.mozilla.org)
| devit wrote:
| As far as I can tell this is only done if the certificate if
| valid for the new domain, so this seems only exploitable if you
| have stolen the certificate public keys.
|
| It might allow to do traffic interception after stealing the
| private keys without MitMing the connection, but in general you
| have to assume the adversary is all-powerful and can MitM
| anything and thus that a stolen certificate private key is
| catastrophic, so it doesn't really change anything in the worst
| case.
|
| It also appears that it needs an address in common, so it doesn't
| even seem a problem from a correctness perspective, since if you
| were fine getting traffic for both domains on the same IPv6
| address (and thus the same endpoint), then why would you not
| support getting it on the same IPv4 address, or viceversa.
|
| Although it's not clear whether it's a good idea, it seems it
| might be better to require that the domains actually have the
| address that was connected to in common rather than any address.
| jsmith45 wrote:
| I could see this perhaps being exploitable against some
| cloudflare clone or shared hosting provider where the following
| setup is used:
|
| One server hosts multiple sites from different end entities,
| with a shared IPv4 address (since those are scarce), and
| obviously a cert that contains SANs for all the sites this
| server instance hosts. On IPv4 the server is configured to look
| inside the request to know which virtual site to serve up.
|
| But for IPv6, they let the each site have a seperate ip
| address, and bind the virtual sites based only on IP address,
| since each one is unique, and we can avoid extra overhead of
| parsing the domain before dispatching this way.
|
| They continue to reuse the multi-san Cert for these addresses,
| because having to manage extra certs when you already have one
| that works for all the sites would be silly.
|
| Now if a connection is open to the attackers site via ipv6, and
| then Firefox tries to open the victim site, resolves the IP
| address, notices that it has an IPv4 match with the attackers
| site, so assumes it can just use the attacker site's IPV6
| connection, since it was using a cert that lists the victim
| domain, and suddenly attacker site starts getting requests
| intended for the victim site, and can do things like steal
| credentials.
|
| Now perhaps this scenario cannot happen. The bug report does
| not fully lay out which domains were involved and which ipv4
| were assigned to which, and I'm not sure exactly how the reuse
| logic in Firefox works.
|
| I'm also unsure if this proposed setup violates some http/2 RFC
| MUSTs, or anything like that, but it is not like it is a
| completely outlandish idea.
| GauntletWizard wrote:
| > obviously a cert that contains SANs for all the sites
|
| This is where your example falls apart, because that's not a
| reasonable thing in the real world. Shared hosts should be
| (and mostly are) using SNI[1], "Server Name Indication". SNI
| basically adds "Tell me which certificate you want to see" to
| the protocol, so your browser starts the request with "I'm
| trying to connect to Site1", and the shared hosting provider
| will have certificates for each individual site they're
| hosting, and pick the right one.
|
| For a real example of how this is dangerout, see jsmith45's
| comment above about wildcards and specific sites.
|
| [1] https://en.wikipedia.org/wiki/Server_Name_Indication
| tialaramex wrote:
| > if you have stolen the certificate public keys.
|
| [nitpick] Private keys. The public keys are published right
| inside the certificate of course.
| voidwtf wrote:
| I'm really not comfortable with how they resolved this as
| invalid.
|
| This seems like it could be ripe for abuse when the host is
| behind a Cloudflare like service, or a CDN with a shared anycast
| infrastructure. Often times these services will use the host name
| in the initial connection to determine the origin. While it would
| be very difficult to turn this into a targeted attack, I could
| imagine that spraying a number of discrete domains across those
| services may result in finding one or more interesting hosts.
|
| This could also cause some quite unexpected behavior if your
| applications/infrastructure sits behind a common reverse proxy
| where all hosts share a *.host.tld certificate pointing to the
| same reverse proxy. Imagine static.host.tld serving you the login
| page, which also tries to make a request to api.host.tld which
| shares the same certificate and IP but with the given host name
| would have been proxied to a different backend server.
| tialaramex wrote:
| > This could also cause some quite unexpected behavior if your
| applications/infrastructure sits behind a common reverse proxy
| where all hosts share a *.host.tld certificate pointing to the
| same reverse proxy. Imagine static.host.tld serving you the
| login page, which also tries to make a request to api.host.tld
| which shares the same certificate and IP but with the given
| host name would have been proxied to a different backend
| server.
|
| If your static.host.tld cheerfully claims to be api.host.tld
| _and_ you gave it a certificate testifying to this claim, then
| it 's really your fault when it can't serve API queries right?
|
| Outfits like Cloudflare handle the mapping properly, even if
| they have arranged a single certificate for this.example,
| that.example and the-other.example, they care whether a
| particular TLS session says it's for this.example or
| that.example and the transactions will accordingly go to the
| correct place. This Mozilla behaviour doesn't cause any
| problems.
|
| This is something a crappy bulk host probably gets wrong using
| Apache httpd since Apache doesn't make even the bare minimum
| effort to actually implement this correctly by default (When a
| TLS client says "Hi I want to talk to api.host.example" and
| there is no such host configured, Apache just figures the
| default host can handle it even though the standard explicitly
| says that's wrong...). Fortunately the crappy bulk host is
| almost certainly just mapping everything through a bunch of
| VirtualHost rules and you probably can't exploit it in the way
| you describe these days, although they should probably really
| use an HTTP server from somebody competent.
| voidwtf wrote:
| I think your missing the part of the bug report where Firefox
| is REUSING the existing TLS connection, which was established
| with a completely different SNI.
|
| If I have a load balancer handling all these connections, and
| I routed a connection through to static-backend-1 then
| Firefox "cheerfully" decided to reuse this connection for
| api.host.tld, how is my load balancer which has already
| handed off the connection to static-backend-1 going to do
| anything about that?
| tialaramex wrote:
| Mozilla are doing this for HTTP/2 which transports the
| entire URI, not like HTTP/1.0 where people just figure hey,
| I needn't send the server's name.
|
| So, the request for api.host.tld says "api.host.tld" on it.
| If your static server receives this request, but isn't able
| to service api.host.tld requests the HTTP/2 specification
| provides an HTTP error code to return 421, saying, oops, I
| can't help you with that - and the specification tells
| clients that in this case they might try asking via another
| route.
| xg15 wrote:
| > _they care whether a particular TLS session says it 's for
| this.example or that.example and the transactions will
| accordingly go to the correct place. This Mozilla behaviour
| doesn't cause any problems._
|
| Indeed they do - via the SNI header, which is set once per
| TLS connection, not once per HTTP request. I would think
| initializing a connection for one domain and then reusing it
| for a different domain could absolutely cause problems.
| Matthias247 wrote:
| CDNs with shared infrastructure make use of domain-fronting
| checks. Those validate that the target of every single request
| (identified by the Host or :authority header) is valid for the
| SNI and associated TLS certificate that was used to establish
| the connection, and otherwise reject the request. That is
| actually independent of HTTP/1.1, /2 or /3, since all of those
| allow for multiple requests targetting different authorities on
| the same connection.
|
| If you build your multi-tenant webserver yourself you however
| obviously have to be careful regarding getting this right.
| icehawk wrote:
| The TLS certificate does explicitly say that it's valid for all
| of the names involved in the report: X509v3
| Subject Alternative Name:
| DNS:chess.samba.org, DNS:etc.samba.org,
| DNS:ipv6-only.samba.org,
| DNS:ipv6-test.samba.org, DNS:ipv6-without-
| ipv4.samba.org, DNS:jitterbug.samba.org,
| DNS:jupiter.samba.org, DNS:linux-
| cifs.samba.org, DNS:mta-
| sts.lists.samba.org, DNS:mta-
| sts.samba.org, DNS:n4.samba.org,
| DNS:netfilter.samba.org,
| DNS:news.samba.org, DNS:rproxy.samba.org,
| DNS:vger.samba.org
|
| It feels like odd behavior but logically it makes sense to trust
| the authenticated info from the SSL certificate.
|
| Personally to resolve all ambiguity I'd just use different
| certificates. Separation of concerns and all.
| marcosdumay wrote:
| It's a problem if you decide to trust a certificate that isn't
| automatically trusted by the browser.
| jsmith45 wrote:
| But let's say I had two severs. One that hosts 1000 different
| subdomains, so I give it a wildcard cert, as 1000 SAN entries
| would be absurd.
|
| The second server hosts one subhuman, and has a specific cert
| for it.
|
| Would Firefox try to send a request for that seperate subhuman
| to my big wildcard server? That sounds very wrong!
|
| It is also possible that I had configured that wildcard server
| to host up some default site for unknown hostnames. Perhaps
| that default site exists to tell people how to report a problem
| if they see it, as with 1000 subdomains it would be very easily
| for there to be an accidental mismatch between the name in DNS
| and the name in the nginx config, especially if relevant
| automation has not been built up yet.
|
| I'd see that as an absolute bug, regardless of what the spec
| says (and the bug report does has some people disputing the
| spec allows doing this without checking DNS first).
|
| Although I suppose it is possible that Firefox won't do this
| for wildcards, but only for explicitly listed SAN names? Which
| is better but still quite odd seeming to me.
| xg15 wrote:
| > _The second server hosts one subhuman, and has a specific
| cert for it.
|
| Would Firefox try to send a request for that seperate
| subhuman to my big wildcard server? That sounds very wrong!_
|
| You might want to clear your autocorrect cache.
| pornel wrote:
| The reporter has discovered that HTTP/2 has a connection
| coalescing feature. Coalescing requires hosts to share the same
| valid TLS certificate. As far as the specs go, this is not a bug,
| and it doesn't violate security model of HTTP/2.
|
| HTTPS is meant to add security on top of unprotected
| untrustworthy network, so it doesn't concern itself with what
| happens on the IP layer which is already assumed to be
| potentially MITMed/spoofed. Here the reporter expects the
| unprotected network to add security in case HTTPS has been
| completely defeated. Good luck with that.
| untitaker_ wrote:
| As the reporter already stated, just because the HTTP/2 spec
| permits it, that doesn't make it a good idea. Now Firefox may
| "resolve" a hostname to a different IP based on whether it
| might have connected to a different hostname before. I don't
| want to imagine what bugs this will cause. And for what? To
| save another (probably already cached) DNS lookup?
| pornel wrote:
| The time to bikeshed whether it's a good idea was at IETF
| when HTTP/2 has been designed. This feature has been in
| production for over 6 years.
|
| Note that both hostnames must be in the same TLS certificate.
| You won't get random hosts coalesced by accident. _You_ have
| to specifically obtain a TLS certificate that contains
| multiple of your hosts, and their DNS entries have to have at
| least one IP address in common. And then the server can still
| return an HTTP error that tells the browser to stop
| coalescing and retry with a fresh connection.
|
| In practice this feature is commonly used to reuse a single
| CDN connection to fetch from multiple hosts behind the same
| CDN (e.g. www.example.com + assets.example.com), and avoids
| fragmenting per-connection request prioritization in HTTP/2.
| toast0 wrote:
| > You have to specifically obtain a TLS certificate that
| contains multiple of your hosts, and their DNS entries have
| to have at least one IP address in common.
|
| But oddly IMHO, the IP used to send requests to both need
| not be in common?
| pornel wrote:
| Yes, because IPs are hard to keep exactly in sync even
| when they reach the exact same machine, e.g. because of
| sharding/load-balancing done by CDNs.
| zerocrates wrote:
| The utility of reuse is clear, but how often is it actually
| necessary to "reuse" a connection to an address that's not
| in the DNS for the hostname you're trying to connect to, as
| here? Seems like it would be very rare.
| zerocrates wrote:
| It seems like it must actually _do_ a DNS lookup to have
| established the matching IPv6 address, so you 're not even
| saving that. (edit: Or maybe it just ignores DNS totally at
| this point and operates off having seeing the second hostname
| in the certificate it got before? That seems like it would
| cause more issues though.)
|
| I'm not sure I totally buy that the spec _does_ allow it
| (since the "authoritativeness" rules for HTTPS are defined
| as being in addition to those for HTTP), but beyond that it
| is a little hard to imagine what purpose there is to be
| overly-greedy like this in matching up for reused
| connections.
| xg15 wrote:
| Doesn't this have the potential to interact really badly with
| SNI though?
|
| After all, TLS today is not "just" a security layer anymore.
| With SNI and ALPN it has also taken on quite a bit of routing
| functionality.
|
| E.g. suppose example.com has two subdomains, foo.example.com
| and bar.example.com. To simplify deployment, the site uses a
| central TLS gateway to terminate all connections to
| *.example.com and also uses a single wildcard certificate for
| all subdomains. The gateway then reads the SNI header to figure
| out which backend server it should proxy the connection to.
|
| This works perfectly fine as long as a browser only uses a
| connection for the subdomain that it announced in the SNI
| header. However, if it suddenly starts to make requests for a
| different subdomain on that connection, because both subdomains
| share the same IP (of the gateway) and cert (wildcard),
| requests will be routed to the wrong backend server and things
| will break.
|
| I'm not sure what the exact conditions for connection
| coalescing are in Firefox. If it's really as you say and the
| certificates have to be _identical_ , then it's just a safety
| issue. However, if it's only required that the certs are signed
| for the same domain, then it could become a security issue as
| well: All you needed was to be on the same shared hoster as
| your victim and obtain a fraudulent cert for their domain and
| you can hijack some of their connections.
|
| Edit:
|
| Also, if the browser has a connection open to foo.example.com
| and wants to make a request to bar.example.com, how does it
| even obtain the cert for bar.example.com to decide if it can
| reuse foo's connection? It would have to open a new connection
| with SNI=bar.example.com, grab the cert - and then _close the
| connection again_ and go back to foo 's connection. What would
| even be gained by that?
| nix0n wrote:
| It looks to me like HTTP/2 can be disabled in Firefox via setting
| network.http.http2.enabled and network.http.http2.enabled.deps
| both to false.
|
| I tested on http://www.http2demo.io/ both with and without those
| settings enabled. The HTTP/2 version doesn't fail when those are
| disabled, but it shows the same result as the HTTP/1 version.
|
| To me this behavior is an argument against Cloudflare more than
| it's an argument against HTTP/2, but mostly I hope that nobody is
| tempted to switch to Chrome about it.
___________________________________________________________________
(page generated 2022-05-27 23:02 UTC)