Skip to content

Instantly share code, notes, and snippets.

@joepie91
Last active September 16, 2023 18:11
Show Gist options
  • Star 76 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save joepie91/7e5cad8c0726fd6a5e90360a754fc568 to your computer and use it in GitHub Desktop.
Save joepie91/7e5cad8c0726fd6a5e90360a754fc568 to your computer and use it in GitHub Desktop.
Why you probably shouldn't use a wildcard certificate

Recently, Let's Encrypt launched free wildcard certificates. While this is good news in and of itself, as it removes one of the last remaining reasons for expensive commercial certificates, I've unfortunately seen a lot of people dangerously misunderstand what wildcard certificates are for.

Therefore, in this brief post I'll explain why you probably shouldn't use a wildcard certificate, as it will put your security at risk.

A brief explainer

It's generally pretty poorly understood (and documented!) how TLS ("SSL") works, so let's go through a brief explanation of the parts that are important here.

The general (simplified) idea behind how real-world TLS deployments work, is that you:

  1. Generate a cryptographic keypair (private + public key)
  2. Generate a 'certificate' from that (containing the public key + some metadata, such as your hostname and when the certificate will expire)
  3. Send the certificate to a Certificate Authority (like Let's Encrypt), who will then validate the metadata - this is where it's ensured that you actually own the hostname you've created a certificate for, as the CA will check this.
  4. Receive a signed certificate - the original certificate, plus a cryptographic signature proving that a given CA validated it
  5. Serve up this signed certificate to your users' clients

The client will then do the following:

  1. Verify that the certificate was signed by a Certificate Authority that it trusts; the keys of all trusted CAs already exist on your system.
  2. If it's valid, treat the public key included with the certificate as the legitimate server's public key, and use that key to encrypt the communication with the server

This description is somewhat simplified, and I don't want to go into too much detail as to why this is secure from many attacks, but the general idea is this: nobody can snoop on your traffic or impersonate your server, so long as 1) no Certificate Authorities have their own keys compromised, and 2) your keypair + signed certificate have not been leaked.

So, what's a wildcard certificate really?

A typical TLS certificate will have an explicit hostname in its metadata; for example, Google might have a certificate for mail.google.com. That certificate is only valid on https://mail.google.com/ - not on https://google.com/, not on https://images.google.com/, and not on https://my.mail.google.com/ either. In other words, the hostname has to be an exact match. If you tried to use that certificate on https://my.mail.google.com/. you'd get a certificate error from your browser.

A wildcard certificate is different; as the name suggests, it uses a wildcard match rather than an exact match. You might have a certificate for *.google.com, and it would be valid on https://mail.google.com/ and https://images.google.com/ - but still not on https://google.com/ or https://my.mail.google.com/. In other words, the asterisk can match any one single 'segment' of a hostname, but nothing with a full stop in it.

There are some situations where this is very useful. Say that I run a website builder from a single server, and every user gets their own subdomain - for example, my website might be at https://joepie91.somesitebuilder.com/, whereas your website might be at https://catdogcat.somesitebuilder.com/.

It would be very impractical to have to request a new certificate for every single user that signs up; so, the easier option is to just request one for *.somesitebuilder.com, and now that single certificate works for all users' subdomains.

So far, so good.

So, why can't I do this for everything with subdomains?

And this is where we run into trouble. Note how in the above example, all of the sites are hosted on a single server. If you run a larger website or organization with lots of subdomains that host different things - say, for example, Google with their images.google.com and mail.google.com - then these subdomains will probably be hosted on multiple servers.

And that's where the security of wildcard certificates breaks down.

Remember how one of the two requirements for TLS security is "your keypair + signed certificate have not been leaked". Sometimes certificates do leak - servers sometimes get hacked, for example.

When this happens, you'd want to limit the damage of the compromise - ideally, your certificate will expire pretty rapidly, and it doesn't affect anything other than the server that was compromised anyway. After fixing the issue, you then revoke the old compromised certificate, replace it with a new, non-compromised one, and all your other servers are unaffected.

In our single-server website builder example, this is not a problem. We have a single server, it got compromised, the stolen certificate only works for that one single server; we've limited the damage as much as possible.

But, consider the "multiple servers" scenario - maybe just the images.google.com server got hacked, and mail.google.com was unaffected. However, the certificate on images.google.com was a wildcard certificate for *.google.com, and now the thief can use it to impersonate the mail.google.com server and intercept people's e-mail traffic, even though the mail.google.com server was never hacked!

Even though originally only one server was compromised, we didn't correctly limit the damage, and now the e-mail server is at risk too. If we'd had two certificates, instead - one for mail.google.com and one for images.google.com, each of the servers only having access to their own certificate - then this would not have happened.

The moral of the story

Each certificate should only be used for one server, or one homogeneous cluster of servers. Different services on different servers should have their own, usually non-wildcard certificates.

If you have a lot of hostnames pointing at the same service on the same server(s), then it's fine to use a wildcard certificate - so long as that wildcard certificate doesn't also cover hostnames pointing at other servers; otherwise, each service should have its own certificates.

If you have a few hostnames pointing at unique servers and everything else at one single service - eg. login.mysite.com and then a bunch of user-created sites - then you may want to put the wildcard-covered hostnames under their own prefix. For example, you might have one certificate for login.mysite.com, and one (wildcard) certificate for *.users.mysite.com.

In practice, you will almost never need wildcard certificates. It's nice that the option exists, but unless you're automatically generating subdomains for users, a wildcard certificate is probably an unnecessary and insecure option.

(To be clear: this is in no way specific to Let's Encrypt, it applies to wildcard certificates in general. But now that they're suddenly not expensive anymore, I think this problem requires a bit more attention.)

@sarink
Copy link

sarink commented Jan 19, 2019

If your certificate is compromised, wildcard or not, you're in trouble. A wildcard cert probably exists in multiple locations and probably is being shared around, therefore it has a greater surface area (probably), and is (probably) less secure. But to simply state, "wildcard certs are less secure", is patently untrue.

@theel0ja
Copy link

I'll do you one better go inspect the https://api.google.com cert. Makes me wonder about the validity of your arguments?

Google uses load balancers (see https://cloud.google.com/security/overview/whitepaper) and the keys probably are stored on hardware security modules.

@theel0ja
Copy link

An example of long-validity period wildcard cert getting leaked while a single subdomain certificate would be enough and more secure:
https://nakedsecurity.sophos.com/2019/10/23/hacker-breached-servers-used-by-nordvpn/

@AnnoyingTechnology
Copy link

AnnoyingTechnology commented Dec 20, 2019

Here's as TL;DR for the lazy

Because your private keys will likely be used on lots of server, and if it gets stolen on one, all your certificates could be faked

@jacobq
Copy link

jacobq commented Aug 10, 2020

Please help me understand my alternatives to wildcard certificates in this situation:

  1. Servers are embedded products without Internet access (something like industrial IoT)
  2. Customer does not want to upload certificates to each device
  3. There can be any number of devices on the same network
  4. Customer wants to specify arbitrary hostnames/subdomains to access the devices on their local network
  5. Customer wants to see "green lock" and "no scary warnings" when connecting to these devices in a modern web browser
  6. Customer does not want to use plain-text / unencrypted HTTP

The only other solution I can think of is to add a trusted CA cert to machines that need to access these devices and then to embed the CA cert's private key on each device and create/sign certs on the fly. However, that seems far less advisable to me.

@joepie91
Copy link
Author

@jacobq There is basically no good answer there. For TLS to be meaningfully secure, you need some kind of mechanism to prevent malicious issuance. For public hostnames, that works by trusting a bunch of external, public CAs to verify domain ownership before handing out a certificate; for internal networks, it usually means an internal CA on well-secured infrastructure that explicitly issues certificates where appropriate.

Any useful certificate, however, is going to be tied to a specific hostname - one that the requester has been validated to control. A wildcard certificate would not be a solution here, as it would allow anyone controlling any such device to intercept traffic of any other device under the same domain name, whether or not they have access to it.

Unless these are devices that are both produced and used by the same organization internally, that would make TLS effectively useless, as any device owner could mess with the traffic of any other device owner. If the devices are produced and used by the same organization, you might as well just set up a VPN and run everything over that instead, since you control it end-to-end anyway - much simpler to deal with.

If these devices are produced for third parties to use in their network, then you will need some kind of enrollment system that generates individual certificates that are valid for a given device's hostname, through some sort of verification mechanism that is appropriate for the setting in which the devices are used.

@jacobq
Copy link

jacobq commented Aug 11, 2020

Thanks for the detailed reply. In this case I think the main problem is in the customer's expectations (though they probably wouldn't like to be told that). That is, they are more concerned about the appearance of the security ("security theater", to borrow Bruce Schneier's term), such as seeing green colors and lock icons vs. scary warning messages (aside: it's often annoyed me that using completely insecure protocols does not result in a scary warning). If some of the constraints I listed were relaxed I think there are a couple reasonable solutions (which you alluded to):

  • Pre-generate & assign a unique hostname and certificate to each device (e.g. sn123456.my-cool-thing.app). Customer could use the device simply by adding an appropriate internal DNS entry for it. Downside is that this may incur high costs if purchasing each of these individual certs from a public CA (though I think some may have more reasonable pricing models for hosts/subdomains once the domain has been validated), and if using a private CA then the customer would have to trust the corresponding CA cert.

  • Have the customer define a hostname and install a certificate on each device. Downside is that this adds more work for the customer. Upshot is that it allows them to have complete control, use their own domain, etc.

@joepie91
Copy link
Author

The title is a conclusion drawn from an explanation that assumes certain behaviors.

The title very clearly says "probably", and the exact conditions and how they affect the outcome are described in detail in the article. Did you read it?

The only real argument I've seen about using wildcard certificates can be summed up in various posts ( especially this one )

Yes, that is the foundational argument. But it's not something that is widely-understood, so a single-line description isn't going to convince anyone. Hence why this article goes into more detail.

that having the same private key on multiple servers ( slightly ) increases your risk if one gets compromised ( and you are pretty screwed when that happens anyway ).

It's not a "slight" increase. It can be the difference between a contained breach and a complete organizational network being overtaken. This difference is significant, and crucial to good security practices.

"Pretty screwed when that happens anyway" doesn't make sense either; it's widely understood in the security world that you will get compromised at some point, somewhere. That's not when you throw up your hands in the air and go "oh well, guess we'll have to shut everything down now" -- it's when you try to make sure that any such breach stays as contained as you can make it, so that the consequences are limited.

But instead of saying that you have ( in my opinion ) longer than necessary articles everywhere about wildcards being bad

It's exactly as long as it needs to be to explain the problem, in such a way that it can be understood by people who aren't very familiar with the topic yet. Not everything can be summarized into a tweet-sized soundbite.

and now we can't use them in my organization, even if the certificate was going to go on one server to replace a SAN certificate with 24 DNS names ( I know, that's a bad thing too, but we need to live with it for now ).

This sounds like the article does exactly what it's supposed to: stop people from using wildcard certificates inappropriately. Even a SAN certificate with many names (which is also bad if it's shared between servers) is still better than a wildcard certificate, because at least it will not be valid for every single thing under the domain.

We need a TL;DR snopes site for things like this.

What, exactly, would you expect a site like Snopes to say? I'm pretty confident that it'd find no problem with what I've written - all the conditions and caveats are clearly outlined.

Should have been named "Situations when wildcard certificates can increase your security risk"

This would not get across the intended message, which is "the situation where you think wildcard certificates are fine, probably isn't".

@lludsubaru
Copy link

Sorry, shouldn't write anything while frustrated; this was the 4th or 5th article I'd read. Most of the post shouldn't have been directed at this post specifically, but the topic in general. I removed it. Thanks for replying back. But I do have a question if your willing: why exactly is a SAN cert better than a wildcard certificate if it's just on one server? And ideally from a practical point of view not theoretical ( ie. what is the scenario that would be able to take advantage of a wildcard cert but not a SAN one )

@joepie91
Copy link
Author

Sorry, shouldn't write anything while frustrated; this was the 4th or 5th article I'd read. Most of the post shouldn't have been directed at this post specifically, but the topic in general. I removed it.

👍

But I do have a question if your willing: why exactly is a SAN cert better than a wildcard certificate if it's just on one server? And ideally from a practical point of view not theoretical ( ie. what is the scenario that would be able to take advantage of a wildcard cert but not a SAN one )

The main scenario where the difference matters, is the one where you end up having another server in the future. The thing with a wildcard certificate is that it works like a 'master key' for a domain - everything that's under that domain, and crucially, everything that will be under that domain in the future, is covered by it.

So say that today you have one server, server 1, and it serves a.example.com, b.example.com, and c.example.com. You might get a wildcard certificate for *.example.com - let's assume for the sake of explanation that it's valid for 1 year. Now, in 8 months, you decide to get a second server, server 2, and host d.example.com on it. For the remaining 4 months that the wildcard certificate is valid, it will also be valid for d.example.com on server 2, and there is nothing you can do about that.

While revocation exists in theory, it's not widely supported for a variety of infrastructural reasons, so from a practical perspective a certificate should be considered valid until its expiry date no matter what happens. This is also why Let's Encrypt has been reducing the validity periods, in an attempt to reduce the 'exposure window' if a certificate gets compromised and revocation doesn't work for whatever reason.

This model of an "irrevocable grant" is quite different from the authentication systems that people deal with on a daily basis, which is why this is often missed. For example, if you change your password on a website, the old password stops working. But with TLS certificates, it's like both passwords continue to work, and the old one needs to expire first, and you can't do anything to speed that up.

This makes it all the more important to never issue an overly-broad certificate. Even if it might seem fine today, you're making a commitment for the lifetime of that certificate that your situation will not change security-wise, and that your "this is fine because..." assumptions will hold up.

(This is true to a lesser degree with SAN certificates, if there's the possibility that you'll move one of the services to a different system in the future. That's just less common, and so a slightly lower risk. But where possible, it's best to avoid that as well.)

@mk-pmb
Copy link

mk-pmb commented Oct 17, 2021

For example, if you change your password on a website, the old password stops working.

Pro-tip: Always verify that expectation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment