PKI Best practices for updating SSL certificates - ssl

What are the best practices for updating client-side SSL certificates without user interaction?
To be more specific:
I have a server with SSL private key/public x.509 certificate.
All clients will communicate with this server through SSL.
In order to establish SSL connection all clients need to import the server's public certificate to their trusted locations (truststore).
Getting the server's certificate at (client) install time is not a problem because the installer can contact the server (by SSL) and get the server's public key (or the company's Root Certificate). After that the installer can show the certificate to the user for visual validation and this is secure enough.
What will happen after the server certificate (or the company CA) expires?
Or what will happen if the server certificate is accidentally changed?
What are the best practices to (automatically) update all clients with the new server SSL certificate (CA)? Having in mind that after installation the clients are background processes and the is not visual user interaction possible.
Of course the easiest way is to manually update all clients by the infrastructure administrator.
I'm wondering if there are some known good practices to automatically update the client's certificates without user intervention?

Ideally, your server certificates should be issued and signed by a trusted root CA certificate with a long lifetime (10 to 20 years). Just the root CA certificate would be installed on the client end.
The server certificate itself, even if you update it every year, would not need to be propogated to clients since the root signed it and is trusted.
If you're using self-signed certificates, this is why they are generally frowned upon from a certificate management perspective. When they expire or change, you need everyone to update - otherwise you'll get browser security warnings.

Related

Why does some SSL clients need to download a server SSL certificate and store it

I'm building a PHP web app that uses AWS RDS. In order to make the connection encrypted, I need to download the SSL certificate from RDS and store it on the app server so that the app can use it. But I remember when I use SQL workbench it somehow knows how to connect with SSL to the RDS instance without me downloading the certificate and telling it where the certificate is stored. Also after reviewing the way how HTTPS works, I know that the client doesn't need to store a certificate the first time it connects to a server, it download the certificate itself. So my question is for my app to connect to RNS instance using SSL, why do I need to first download the cert and tell my app where it's stored? Shouldn't my app know how to get the certificate itself?
Certificate validation requires a trusted root CA. Trusted means that the CA is in the local trust store. Depending on what site you connect to and what certificate you get it might be a certificate issued by a CA you already trust or not. In the latter case you would need to explicitly get the so far untrusted CA certificate first and somehow treat it as trusted.
The need to explicitly import a CA as trusted is typically true for self-signed certificates which is usually considered bad practice but depending on the specific environment might make sense. It can also happen for company specific CA but these should better by rolled out to the various systems by an automated process. It might also happen when a misconfigured server does not send a required intermediate certificate, in which case it would be better to fix this server.
Note that you should not import arbitrary CA certificates and consider these trusted. Whoever owns this CA can issue arbitrary certificates even for existing domains like google.com and your application will then blindly trust these faked certificates too, making man in the middle attacks possible.

How to set client certificate chain in WinHttp

I am working on a client-server application where server is a web server which performs client validation based on SSL certificate. Server trust a Root CA certificate. Client is a windows application developed in C++ which has a certificate signed by intermediate CA which in turn signed by Root CA.
I am able to set client certificate during https connection by calling WinHttpSetOption api with WINHTTP_OPTION_CLIENT_CERT_CONTEXT as option. However this will set only client certificate but not the entire chain. Server does not have intermediate CA in its store hence it is not able to authenticate the client.
Is there a way to set the full client certificate chain in WinHttp, provided the full chain is already present in certificate store of client?
The server has to have the CA certificate beforehand, it's not going to trust the root CA the client hands it. (I'm not sure about whether it (the server-side) would trust an intermediate CA signed by a trusted CA but my inclination says no).
Trusting some random CA a client sends would break the entire point of certificate verification, you would have no idea of whether the data the client submits is actually meaningful. So add the root and intermediate CA certificates to the server's certificate stores. (If you don't have access to that you'll have to talk to an admin and have them do it).
I'm not really seeing anything wrong with what you are doing.
You are implementing mTLS. The client side has a private key that it uses to validate itself to the Server. Most times the client will generate this private key itself and just send it to the server via CSR. In your case you have some CA generate it for you.
mTLS is used in place of some other sort of login a client might do to a server. The client itself doesnt care about the cert chain. The client doesnt need to validate itself. It just sends a token encoded via its private key. The server DOES need the root or intermediate cert in order to validate the key the client has sent. Usually you just install this root into your normal cert store (server side) so the server can validate the client.
Only I could find was to Add Sub CA to system store. During service startup or installation, open the CA certificate store and Add certificate context to it.

What is the difference between SSL pinning (embedded in host) and normal certificates (presented by server)

I'm not quite understanding the necessity of certificate pinning in SSL connection establishment (to avoid Man in the Middle attacks).
SSL cert pinning requires embedding original server certificate in the host to verify with the one presented by server. what is the difference between the server certificate embedded in the host and the one presented by server to be validated by client?
What is that I am missing here?
what is the difference between the server certificate embedded in the host and the one presented by server to be validated by client?
There should be none and that's exactly the point of certificate pinning.
Without certificate pinning an application commonly accepts any certificate which matches the requested hostname and is issued by a locally trusted CA (certificate authority). Given that there are usually more than 100 CA in the local trust store it is sufficient that one of these got successfully attacked as in the case of DigiNotar in 2011. Thus it makes sense to limit the certificate you accept to a specific one, i.e. pinning.
Besides the certificate pinning by comparing the certificate received with a locally stored certificate there are other ways of pinning: for example one might just check against a fingerprint (hash) and not the full certificate. In case the certificate can expire it might be more useful to check only the public key and not the whole certificate because the public key is often kept on certificate renewal. Or one might pin to a specific CA which one considers trusted to issue certificates for this domain.
Note that to understand pinning you might need to understand how the authentication of the server works. One part of this is that the server certificate is validated (hostname, expiration, trust chain ...). But this is not enough since the certificate itself is public, i.e. everybody can get it and could send it inside the TLS handshake. Thus the other major part of the authentication is that the server proves that it is the owner of the certificate. This is done by signing some data using the private key matching the certificate. Since only the owner of the certificate should have the private key this proves ownership. Because of this anybody could embed the servers certificate for pinning but only the server itself can prove ownership of the certificate.
What is SSL pinning
Applications are configured to trust a select few certificates or certificate authority (CA), instead of the default behaviour: to trust all CAs that are pre-configured on the device/ machine. SSL pinning is not required.
Why use SSL Pinning (Why not to)
In many cases, the certificate returned by a server could be tampered as long as any Root (or intermediate root) CA was compromised (happens very rarely). Threat actors could use this compromised CA to generate a certificate for your website, and show visitors their website instead. This is bad. SSL pinning was designed to prevent this in some cases, but there are better ways (IMHO).
Having said that, I don' t know any website which uses SSL pinning so SSL pinning seems primarily discussed for mobile apps. It seems like SSL pinning only works when you can trust the source of the application (e.g. App Store, Play Store) Why? Because if you have to visit a website to get the cert, by then its too late (you might have already used a dodgy cert and accessed the fake website or was MITM'd). Therefore, it seems like the benefits Steffen mentioned are not so compelling, especially when there are better solutions already:
Better solution
I'm not sure if any-CA-compromise is a threat vector, even for banks. Instead, banks and other security conscious organisations will pick their CA wisely, and also configure a CAA record.
By using a CAA DNS record, they can restrict clients (e.g. browsers, mobile apps) to trust only certain certificates when accessing their specific website.
They pick the CA and create a cert only from this CA
They will have a backup plan for if a CA is compromised. Don't want to go into that here, but the backup plan for CAA records is IMHO much better than that of SSL pinning.
For example, Monzo.com (I used whatsmydns to find this) has a CAA record which restricts certificates to only 4 CAs (digicert, amazon, comodoca, buypass):
0 iodef "mailto:security#monzo.com"
0 issue "amazon.com"
0 issue "buypass.com"
0 issue "comodoca.com"
0 issue "digicert.com"
0 issue "letsencrypt.org"
0 issuewild "amazon.com"
0 issuewild "comodoca.com"
0 issuewild "digicert.com"
0 issuewild "letsencrypt.org"
These are popular CAs which people trust, we hope they don't let us down. If they do, the whole internet would be a free for all. The only way to prevent this is to be your own CA/ use self-signed certificates.
Summary
I don't see how SSL pinning will become ubiquitous, especially since it adds more overhead (maintenance regarding ssl expiry, or trusting one CA anyway - SPoF, or emulating what a CAA record does but with additional code/ maintenance burden). It also only supports your pre-installed applications, not websites.

HTTPS without installing a trusted CA certificate on browsers

I have some local virtual servers simulating an Intranet at home. I have server who acts as a Root CA and also as a Intermediate CA. I have a web server configured to use HTTPS with a certificate signed by the intermediate CA.
Question: Is there a way to use HTTPS without installing the Root Certificate or the certificate chain file on every web browser of the Intranet clients?
No, the certificates must be installed into the CA root trust store on each individual system. If you have a domain with Windows clients you can use group policy objects to perform the distribution but other than that I'm afraid you'll need to do it the old fashioned way (which can be cumbersome depending upon the platform; like chromebooks).

Can I create my own root certificate to use for an SSL connection with Go? Is this safe?

I'm writing a simple client and server using Go. I don't want to pay for an SSL certificate, and I've read that self-signed certificates are useless for proving identity since an attacker could just MITM and provide his own self-signed certificate.
However, I've learned that I can have my client use whatever root certificates I want. Can I just create my own, have the client trust that, sign a certificate for my server, and connect securely while being protected from MITM attacks? If so, how do I create my own root certificate?
A self-signed certificate is a special case of deploying your own PKI (pushed to the extreme where you only have one certificate in that PKI).
Both can be used to prevent MITM attacks, provided that the client can verify the server certificate using trust anchors (certificates) it knows in advance (and has been configured with them in a trusted manner).
You can create your own CA and configure your client to use its root CA certificate or, if you only have a very limited set of servers, you can usually configure clients to trust a specific certificate directly (self-signed or not).
You may be interested in these questions for links to tools:
Solutions to sign certificates
Recommendations for a Certificate Management tool for Linux
OpenSSL's CA.pl (useful, but may lack general management interfaces)
Once you've understood the basic principles, the technical aspects are not necessarily difficult, but part of the real difficulty is in the administration of your CA.