caddy: Caddy serves wrong SSL cert for site that is not served on HTTPS port

1. What version of Caddy are you running (caddy -version)?

Caddy 0.9.3

2. What are you trying to do?

I want to have multiple virtual hosts, some https, some http only. I want the http only hosts to not respond to https requests with a wrong certificate.

3. What is your entire Caddyfile?

https://foo.example.com {
  tls self_signed
  root /html/foo
}

http://bar.example.com {
  tls off
  root /html/bar
}

4. How did you run Caddy (give the full command and describe the execution environment)?

I created the reproducible example from above on my Mac (10.11.6) but I am having this problem in production on Ubuntu 16.04.1 LTS so I don’t think it is OS related. The working directory contains the Caddyfile from above.

$ sudo caddy

5. What did you expect to see?

Caddy starts fine and serves both vhosts, one with https and the other with http. I expect Caddy to not respond at all when I try to access https://bar.example.com as that virtual hosts is explicitly configured as http, not https.

6. What did you see instead (give full error messages and/or log)?

When accessing https://bar.example.com (the host which is explicitly http), Caddy sends the cert for foo.example.com, which results in an SSL error. (I know that in this example it always results in an error because the cert is self signed, but in production this would serve a trusted cert from Let’s Encrypt).

When ignoring the warning, Caddy responds with No such site at :443. While this is technically correct, Caddy should not accept the connection in the first place.

In addition to the SSL error, this also leaks information about at least one other site (the one Caddy takes the certificate from) that is set up on the host.

7. How can someone who is starting from scratch reproduce this behavior as minimally as possible?

  1. Use the Caddyfile from step 3.
  2. Update the root directive so that Caddy finds some files to serve
  3. Edit your /etc/hosts to include the following
  4. Start Caddy as described in step 4.
# /etc/hosts
127.0.0.1 foo.example.com
127.0.0.1 bar.example.com

Thanks so much for any responses. I’m sorry if there is already an issue for this or if this is a known bug, I couldn’t find anything related to this.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 42 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Okay, so we switch the default behavior to a TLS alert, but with the option to present a default certificate that can be enabled from the Caddyfile. All in favor?

(One problem with this: the presence of the tls directive will enable TLS unless tls off is used… we’d need to figure out how to handle this before continuing.)

@ghoeffner You can email me at tobyallen@gmail.com not sure I will be able to give you a statement though.

@Zenexer Caddy is first and foremost an opensource product. All development is done in the open. The only thing that is commercial is the precompiled binaries. All source is on github.

@mholt The private part here is the association between certificates. Yes, I’m aware it’s possible to derive similar information with sufficient scanning; however, there are technologies that make this difficult, if not impossible (when use correctly), such as Cloudflare. I was able to exploit this to determine the identity of a website operator; I would not have been able to determine their identity had this vulnerability not existed. CT logs were insufficient for this purpose, and there weren’t adequate associations logged in services such as CertGraph and Censys at the time.

tl;dr Yes, it’s a vulnerability, and yes, it’s been successfully exploited. CT logs and CertGraph were unable to provide the same information.

@Zenexer There is a trivial workaround for this, see @ghoeffner above. Perhaps we should add that to documentation until such time as we have a viable fix.

If there are ideas on how this could be fixed in the codebase in an acceptable manner we would be delighted to discuss a PR.

Thanks @Zenexer . I was trying to get a seperate issue opened specifically about the https://:443 issue that we can look at resolving. It is mixed up with an older issue here so by reporting it as a seperate issue it can get dealt with.

I’m happy for you to open it.

@ghoeffner would you mind opening an seperate issue for the problem you described?

FYI: I’m currently in the process of doing some upgrades to Caddy’s TLS package.

Once these changes land, I expect that:

  • Caddy will not serve a certificate for unrecognized SNI names (TLS alert instead)
  • Caddy will serve a ‘default’ certificate for empty SNI names (no SNI)

if all goes well.

Going to wait and see how Go handles the linked issue before we take action on this.

I have noticed a similar and likely related issue: the way things currently are, my caddy server volunteers free information to anyone accessing it through its (current, dynamic) ip by presenting a certificate for one of its subdomains. I’d rather have anyone scanning random ip addresses work a bit harder for that information.

Good point. But: This would only work in the case where I have https://www.example.com and http://example.com. As soon as I add in a third virtual host like https://foo.com, there is the possibility (depending on the order in the Caddyfile maybe?) of serving the foo.com cert for requests to https://example.com, which then Chrome wouldn’t redirect anyways, no?

Right, the redirect is only to www.example.com if the requested hostname was example.com and the cert is valid for www.example.com, or vice versa. It doesn’t apply for any other types of name mismatches. I agree that the right way for servers to handle this is to explicitly redirect to www.example.com.

@mholt I think that “certificate fallback” should be added globally (per server, not per vhost). WDYT?

A note about Chrome: when Chrome encounters a certificate name mismatch error for example.com, with a certificate that is valid for www.example.com, it’ll redirect the user to www.example.com (and vice versa). Changing to a TLS alert would stop this heuristic from working for Caddy servers. Nevertheless, I think a TLS alert is the right way to go: as @mholt said, certificate errors should signal attacks, not server misconfigurations.

Chrome’s www redirect heuristic only kicks in for a small percentage of name mismatch errors, so I don’t expect this would cause a huge increase in the number of errors that users see.

(Plus, maybe there’s some way we can adapt the heuristic so that we do the redirect to www.example.com if connecting to example.com results in the TLS alert.)