Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"openssl verify" gives OK for bad certificate chain

There is a self-signed root CA certificate, rootcert.pem, with the following V3 extensions:

X509v3 extensions:
    X509v3 Key Usage: 
       Certificate Sign
    X509v3 Basic Constraints: 
       CA:TRUE

The rootcert.pem has CA flag set to true & its key usage permits certificate signing. The rootcert.pem signs a certificate foocert.pem with the following V3 extensions:

X509v3 extensions:
    X509v3 Basic Constraints: 
        CA:FALSE
    X509v3 Key Usage: 
        Digital Signature, Non Repudiation, Key Encipherment

The foocert.pem has CA flag set to false & its key usage does not permit certificate signing. But lets say, the foocert.pem signs a rougecert.pem.

Form a certificate chain of foocert & roguecert:

cat foocert.pem roguecert.pem > roguechain.pem

Verify using openssl verify. The verification is successful:

$ openssl verify  -CAfile rootcert.pem roguechain.pem 
roguechain.pem: OK

Verify with x509_strict, still its successful:

$ openssl verify -x509_strict -CAfile rootcert.pem badchain.pem 
badchain.pem: OK

Lets say a system trusts just the root CA certificate. A peer gives its certificate chain, where one of the intermediate certificate is not supposed to be a CA (CA set to false & key usage does not permit certificate signing), still the openssl flags the chain is good?

How do I make openssl not trust such chains?

like image 678
user3574637 Avatar asked Apr 25 '14 22:04

user3574637


People also ask

How do you resolve certificate chain issues?

To resolve the chain issue: Search your Certificate Authority's (CA) website to download their intermediate CA file. This file links all of the trusted CA certificates needed to reach the root certificate. When this Intermediate CA file has been downloaded, you must upload it to the LoadMaster.

How does openssl verify certificate?

The lookup first looks in the list of untrusted certificates and if no match is found the remaining lookups are from the trusted certificates. The root CA is always looked up in the trusted certificate list: if the certificate to verify is a root certificate then an exact match must be found in the trusted list.


2 Answers

(edit: just noticed my answer is a longer and more detailed version of Chris Lesner's, I'd vote him up but I don't have the rep here yet :>)

I think you're still on the wrong track here. I think the actual issue is that 'verify' does not verify chains in a single file in this way.

The final argument to 'verify' is listed as [certificates] and documented thus:

   certificates
       One or more certificates to verify. If no certificates are given, verify will attempt to read a
       certificate from standard input. Certificates must be in PEM format.

You can pass multiple files - but each will be verified as a single leaf certificate, independent of the others. And it's not absolutely explicit, but it implies (and I can tell you that it is in fact the case; see code locations below for details) that one certificate will be read from each file. If you feed it a file containing multiple certificates concatenated together, it will in fact just verify the first certificate from the file as a leaf certificate, and entirely ignore the others.

Thus in your example, what you actually did was verify foocert.pem as a leaf certificate, because it's the first certificate in your roguechain.pem. foocert.pem is valid as a leaf certificate, even with -purpose sslserver. man x509 section CERTIFICATE EXTENSIONS documents the conditions for the 'SSL Server' purpose:

   SSL Server
       The extended key usage extension must be absent or include the "web server authentication" and/or one
       of the SGC OIDs.  keyUsage must be absent or it must have the digitalSignature, the keyEncipherment set
       or both bits set.  Netscape certificate type must be absent or have the SSL server bit set.

and you can see that your foocert.pem has no extended key usage and is not a Netscape type certificate; it does have key usage, with both Digital Signature and Key Encipherment bits set. Therefore, it passed the test.

To do the check you really wanted to do, you have to do this:

openssl verify -CAfile rootcert.pem -untrusted foocert.pem -purpose sslserver roguecert.pem

using the filenames you gave in your initial question. Basically, it's a reasonable simplification to say that you provide root CA certs as -CAfile, -CApath, or -trusted, intermediate CA certs as -untrusted, and the leaf certificate(s) to be validated as the final argument(s).

Note that the file passed as -untrusted can contain multiple certificates concatenated together:

   -untrusted file
       A file of untrusted certificates. The file should contain multiple certificates in PEM format
       concatenated together.

If you want to follow the code to confirm this, each leaf certificate file is loaded by load_cert() in apps/apps.c. The return for that function is X509; X509 objects are single certificates. Compare with load_certs() in the same file, which returns STACK_OF(X509) - that's what OpenSSL typically uses for raw certificate chains.

like image 146
Adam Williamson Avatar answered Sep 19 '22 14:09

Adam Williamson


The original answer proved to be wrong, so here's another one :)

It looks like openssl verify does only the certificate chain verifications and it doesn't check any flags (even with correct -purpose set). The library however does check the flags when you actually do an ssl/tls connection:

$ openssl s_client -verify 100 -CAfile cacert.pem -connect servername:443
verify depth is 100
CONNECTED(00000003)
depth=1 /CN=middle
verify error:num=24:invalid CA certificate
verify return:1
depth=1 /CN=middle
verify error:num=26:unsupported certificate purpose
verify return:1
depth=2 /CN=root
verify return:1
depth=1 /CN=middle
verify return:1
depth=0 /CN=leaf
verify return:1
---
Certificate chain
0 s:/CN=leaf
  i:/CN=middle
1 s:/CN=middle
  i:/CN=root
---
...
SSL-Session:
    Protocol  : TLSv1
    ...
    Verify return code: 26 (unsupported certificate purpose)
like image 43
paulus Avatar answered Sep 18 '22 14:09

paulus