Manual Verification of SSL/TLS Certificate Trust Chains using Openssl
/* This is a blog cross-post from a two-part article published on Taddong's Security Blog */
This week, during my Internet Storm Center (ISC) shift, Firefox 3.6.3 (the latest available version) displayed a digital certificate error when accessing the ISC login page through SSL/TLS: https://isc.sans.org/myisc.html. I confirmed this on a couple of Firefox instances running on Mac OS X and Windows XP.
We also got a few reports from ISC readers on the same issue, although other people running the same browser version, and even language (EN), on the same OS platforms, didn't get any error message. Finally, the reason was a new ISC digital certificate had been recently installed, and the required intermediate certificate was missing in some web browsers. As a result, the browser couldn't validate the full digital certificate chain to ensure you were really connecting to the website you intended to connect to.
This is a common scenario on security incidents, where Man-in-the-Middle (MitM) attacks or direct web server breaches modify the SSL/TLS certificate offered to the victim, and when accidentally accepted, the attacker can intercept and modify the "secure" HTTPS channel. As you may find yourself dealing with a similar situation in the future... how can you (as I did) check what is the real reason behind the SSL/TLS certificate validation error? By manually verifying the SSL/TLS certificate trust chain, or certificate hierarchy, through openssl.
The goal is to manually follow all the validation steps that are commonly performed it an automatic way by the web browser.
Step 1: Check the certificate validation error and download the controversial digital certificate.
$ openssl s_client -connect isc.sans.org:443 |
From the output, ans specifically the verify return code at the end, you can see that the server certificate cannot be verified.
First of all, create a "certs" directory to put all the required files in. Copy and paste to a file ("ISC.pem") the digital certificate, that is, the text between "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----" (including both lines).
Step 2: Identify the issuer and get its certificate.
Open the "ISC.pem" certificate file (by double-clicking on it on most operating systems) and inspect the following fields:
- The certificate thumbprint or fingerprint that identifies the server certificate: "bd:95:df:ac...46:aa" (SHA1).
- Issuer (under the "Certificate" section): Who did generate and issue the server certificate? "USERTrust Legacy Secure Server CA" from "The USERTRUST Network".
- The "Certificate Authority Key Identifier" or fingerprint (under "Certificate - Extensions"): "af:a4:40:af...86:16".
- The "Authority Information Access" (under the same section): It contains a pointer to the digital certificate of the issuer certification authority (CA): "URI: http://crt.usertrust.com/USERTrustLegacySecureServerCA.crt".
Obtain a copy of the issuer certificate. The most secure option would be to get its certificate through HTTPS and not HTTP, but this only depends on how the CA decided to make it available. Double check with the CA website that the URL and the fingerprint are valid. In this case, USERTrust was acquired by Comodo, and the issuer certificate is available here (https link) and referenced in its list of certificates. This certificate belongs to the USERTrust intermediate CA and was the one not available in Firefox 3.6.3 by default, hence, the root cause of the initial SSL/TLS error on the ISC website.
Although you might be tempted to perform the manual verification all from the command line, it is not the most secure option, as you could be forced to use http vs. https when using wget or curl. Depending on the version and platform of these tools, they may be distributed without a default list of trusted root certificates or do not use the list available on the system. Therefore, ** this is NOT the way to get the intermediate certificate **, use a web browser instead:
$ wget http://crt.usertrust.com/USERTrustLegacySecureServerCA.crt |
Step 3: Try to verify the digital certificate again, but this time make use of the previously downloaded certificate ("USERTrustLegacySecureServerCA.crt").
Before using the downloaded certificate, we need to convert it to the PEM format (not required this time; exemplified later), and build the certificates directory required by the openssl "-CApath" option. The Unix "c_rehash" script helps to create the appropriate directory structure and certificate hash symbolic links. Be sure to rename all the certificates in PEM format to .pem, such as "USERTrustLegacySecureServerCA.crt":
$ c_rehash ./certs |
If we try to validate the certificate again, and if we already have the certificates for all the intermediate and root CA's identified in the trust certificate chain stored on the "certs" directory, we will get a positive response: "Verify return code: 0 (ok)".
$ openssl s_client -CApath ./certs -connect isc.sans.org:443 |
If the certificate chain or hierarchy contains additional certificates, that is, there are multiple intermediate CA's involved, you may need to repeat the same process and download the certificates for all the other intermediate CA's and the root CA (omitted for brevity). For example, the intermediate USERTrust certificate was issued by "Entrust.net Secure Server Certification Authority". This root CA certificate can be manually obtained in DER format from Entrust website, with a fingerprint of "f0:17:62:13...d0:1a".
Once again, this DER file must be converted to PEM format using openssl:
$ openssl x509 -in entrust_ssl_ca.der -inform DER -outform PEM -out entrust_ssl_ca.pem |
Finally, you will need to rebuild the certificates directory again, using "c_rehash", once it contains all the intermediate and root CA certificate files that belong to the certificate chain being tested, and try to verify the certificate again.
We used the Internet Storm Center certificate as an example, whose chain has three elements: the ISC (isc.sans.org) certificate, an intermediate USERTrust CA, and the Entrust root CA.
A quick look in the Firefox Preferences (Mac OS X) or Options (Windows and Linux), and specifically on the "Advanced - Encryption - View Certificates - Authorities" section, confirms the intermediate CA certificate from USERTrust was the one missing on Firefox 3.6.3 and, therefore, the one invalidating the certificate trust chain. None of the available USERTrust certificates has the right fingerprint, "af:a4:40:af...86:16".
The client browser does not have the intermediate certificate to be able to verify the full certificate trust chain, and generates the error.
The most common method to avoid this type of certificate validation errors at the web server level, thus for all the web server clients, is by delivering the missing intermediate certificate from the web server itself to the client at connection time.
In the Apache web server world, you simply need to get a copy of the intermediate certificate, in this case "USERTrustLegacySecureServerCA.crt" (see Part 1), and enter a reference to it through the "SSLCertificateChainFile" directive in the Apache configuration file, "httpd.conf", and specifically, in the section associated to the virtual host. Example for the ISC web server (not the real config file):
<virtualhost 10.10.10.10:443> |
These three mod_ssl directives point to the server certificate, the server private key, and the intermediate CA certificate, respectively.
End-user awareness regarding the acceptance of invalid digital certificates is a must!
----
Raul Siles
Founder and Senior Security Analyst with Taddong
www.taddong.com
Comments
but actually, may i ask something?
how can we get session key on ssl. In my mini thesis, i try to implement a "secure cookie protocol" concept http://www.cse.msu.edu/~alexliu/publications/Cookie/cookie.pdf
but i have problem to get the session key in ssl.
if you don't mind, would you help me to find the answer? thank you very much.
tianarang@gmail.com
May 2nd 2010
1 decade ago
When this is done, typical clients will be able to verify the intermediate cert back up to the already trusted root that signed it, and as a result, the server cert will then "chain up" to the already trusted root. The intermediary is trusted by the browser because the root trusts the intermediary. "Web of trust" indeed.
When SSL servers do not return the cert chain in the server key exchange, it is up to the client to decide if the named intermediate certificate should be trusted. Since the cert is not available to verify, it is typically untrusted, prompting an error to the user-agent.
iamfromit
Oct 21st 2010
1 decade ago