Revoking client SSL certificates
Following on from last weeks post, this post is going to look at revoking client SSL certificates to invalidate them.
Why revoke certificates?
When certificates are used for client authentication, the private key is kept on the users device to decrypt messages and the public key is sent to the server. So if Alice wants to connect to Bob's server she will send her X.509 certificate as part of the TLS handshake:
It is important that the private key remains confidential. If the key is compromised, the third party will be able to use the key to impersonate the user. For example if Mallory made a copy of Alice's private key she could use this to authenticate with Bob's server:
Once a private key is compromised any certificates associated with that key should be revoked to ensure they can no longer be used to authenticate. In the example above Bob could revoke Alice's original certificate, and then issue a new certificate to Alice. This will prevent Mallory using the original certificate to authenticate as Alice.
Creating a Certificate Revocation List (CRL)
Start by creating a clrnumber
file. Like the serial
file, this file is used
to add a monotonically increasing sequence number to CRL
certificates as they are generated:
echo 1000 > /etc/httpd/conf/ca/crlnumber
A CRL certificate can then be generated using the following command:
openssl ca \
-config /etc/httpd/conf/ca/openssl.cnf \
-gencrl \
-out /etc/httpd/conf/ca/crl.pem
The new certificate file will initially state that no certificates have been revoked:
$ openssl crl -in /etc/httpd/conf/ca/crl.pem -noout -text
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: /C=GB/ST=England/O=Alice Ltd/OU=Alice Ltd Certificate Authority/CN=Alice Ltd Root CA
Last Update: Oct 8 17:27:12 2017 GMT
Next Update: Nov 7 17:27:12 2017 GMT
CRL extensions:
X509v3 CRL Number:
4096
No Revoked Certificates.
To revoke a certificate, a command similar to the following can be used:
openssl ca \
-config /etc/httpd/conf/ca/openssl.cnf \
-revoke /etc/httpd/conf/ca/newcerts/1000.pem
Finally a new CRL certificate can be generated:
openssl ca \
-config /etc/httpd/conf/ca/openssl.cnf \
-gencrl \
-out /etc/httpd/conf/ca/crl.pem
The certificate will now be listed as revoked:
$ openssl crl -in /etc/httpd/conf/ca/crl.pem -noout -text
...
Revoked Certificates:
Serial Number: 1000
Revocation Date: Oct 8 17:36:38 2017 GMT
Updating Apache
By default Apache will not look at the CRL certificate. As a result revoked
certificates can still be used to authenticate! To correct this add the
SSLCARevocationFile and
SSLCARevocationCheck directives to
/etc/httpd/conf.d/ssl.conf
:
SSLCARevocationFile /etc/httpd/conf/ca/crl.pem
SSLCARevocationCheck chain
Then restart Apache to pick up the configuration change:
systemctl restart httpd.service
Apache should now reject authentication attempts which are made using revoked certificates:
$ curl \
--insecure \
--cert /etc/httpd/conf/users/alice/cert.pem \
--key /e tc/httpd/conf/users/alice/key.pem \
https://localhost/test.txt
curl: (58) SSL peer rejected your certificate as revoked.
Note: if a new CRL certificate is issued, Apache needs to be restarted to pick up the change!
Other security measures
As well as checking for revoked certificates, below are a few security related points you should consider when using client certificate authentication:
-
The certificate authority should ideally be hosted on a different server. This prevents the CA being compromised if the server running Apache is compromised.
-
Add a passphrase to both client and CA private keys. This can be done with the following command:
openssl rsa -aes256 -in key.pem -out key_encrypted.pem
-
Consider using an intermediate CA and storing the private key for the root CA offline. For more information on setting up an OpenSSL CA have a look at the OpenSSL certificate authority guide by Jamie Nguyen.