Fully Verifying Cross-Signed SSL Certificates

Wade Rossmann
2 min readJun 8, 2020

--

There seems to have been a rash of Root and Intermediate CA certificate expirations recently, and while I was busy laughing at the people unprepared for this I got the results of a scheduled security scan telling me that on of the intermediates on our primary site had expired a week ago.

“Woops. Wait… a week ago?” I had a hard time believing that a busy e-commerce site could go a week with broken SSL and zero complaints.

After digging into it I found that when we renewed our certs with Sectigo just a couple months ago they provided us with a cert bundle that included their signing CA, and the expired intermediate. [gee, thanks Sectigo] The reason that nothing broke in an obvious manner was that the Sectigo CA was also cross-signed by a root, and another intermediate CA. So, unless someone was running a 5+ year old device that had never updated, there was at least one valid certification path.

That said:

  1. I can’t abide an invalid cert hanging out there, and the security scan sure doesn’t either.
  2. I need to test both cert paths before pushing changes to a live site.

The trouble is that an openssl verify will always choose the shortest path, eg: me > Sectigo > root, and I want to test me > Sectigo > intermediate > root.

In order to test a specific path like this you need to manually construct it.

  1. Find the root certificate you want to use.
    In my case [CentOS] the certificate was bundled into /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem, and from prior testing I knew it was named “AAA Certificate Services”. Super-trustworthy name, I know. But it’s actually Comodo’s root, and Comodo is now Sectigo, and I don’t know why they’ve done any of this.
    Anyhow, if your cert is stuck in a bundle, copy/paste it into it’s own file somewhere, eg: aaa_root.crt
    If you’re using a Debian-based distro you’ll likely find the individual cert files symlinked in: /etc/ssl/certs
  2. Break out your intermediates into their own files.
    This ensures that you can build out the chain exactly as you’d like.
    eg: usertrust_intermediate.crt and sectigo_intermediate.crt
  3. Construct the openssl verify command:
openssl verify \
-show_chain \ # make sure it's following the chain you've laid out
-CAfile aaa_root.crt \ # use ONLY this root cert
-untrusted usertrust_intermediate.crt \ # untrusted intermediate 1
-untrusted sectigo_intermediate.crt \ # untrusted intermediate 2
my_site.crt

Note: The comments after the escape are invalid syntax, make sure you remove them if you copy/paste this.

You should get output like:

my_site.cert: OK
Chain:
depth=0: CN = example.com (untrusted)
depth=1: C = GB, ST = Greater Manchester, L = Salford, O = Sectigo Limited, CN = Sectigo RSA Domain Validation Secure Server CA (untrusted)
depth=2: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority (untrusted)
depth=3: C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services

4. Repeat as necessary for any other cross-signed paths you’d like to validate.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Wade Rossmann
Wade Rossmann

No responses yet

Write a response