Whenever the server presents its certificate chain to the client during TLS negotiation, the client needs to decide whether it wants to trust that certificate chain and believes that it’s actually talking to the legitimate server and not an impostor.
If a client is tricked into communicating with a rogue application instead of the real server, such as through DNS hijacking, then that application could steal the client’s credentials or trick the client into believing that it has performed some action that it really hasn’t. If the rogue application forwards client communication on to the legitimate server, then it could be even harder for the client to detect the trickery, and even easier for that application to steal data or alter communication. This is why it’s vital to avoid using “trust all” or “blind trust” options in a production environment.
The steps that a client should take when determining whether to trust a server certificate chain include:
- The client should ensure that it has the complete certificate chain. If the server presented an incomplete chain, then the client should ensure that it can complete the chain with information in an explicitly provided trust store or a default trust store. If the client can’t complete the certificate chain, then it should not be trusted.
- The client should ensure that each subsequent certificate in the chain is the issuer certificate for, and that its private key was used to sign, the certificate that precedes it. If a certificate chain contains extraneous certificates, or if a subsequent certificate was not the issuer for the certificate that precedes it, in which case the certificate’s signature would not match the expected value, then the chain should not be trusted.
- The client should ensure that it has a reason to trust the certificate at the root of the chain. This is generally done by ensuring that the root certificate authority (CA) certificate can be found in either a trust store configured for use by that client or a default trust store provided by the operating system, Java Virtual Machine (JVM), browser software, or other trusted source. If the client does not have any prior knowledge of the root CA certificate, then the chain should not be trusted.
- The client should verify that the current time is within the validity window for each certificate in the chain. If any certificate in the chain has a notBefore value that is later than the current time or a notAfter value that is earlier than the current time, then the chain should not be trusted.
- The client should verify that the server certificate, the one at the head of the chain, is suitable for the server that the client thinks it’s communicating with. It should verify that the address it used to establish the connection matches an address contained in the certificate’s subject alternative name extension or in the CN attribute of the certificate’s subject.
The client can perform additional types of validation. For example, if any of the root or intermediate certification authorities maintains a certificate revocation list (CRL) or supports the online certificate status protocol (OCSP), then the client should verify that none of the certificates in the chain has been revoked. It can verify that the CA certificates include the basic constraints extension and that the server certificate isn’t too many levels deep. Other checks, like those using certificate policy extensions, can also be performed.