How can you verify that the SSL client library validates the certificate of the server to which it connects?

I want client libraries (currently in Python, Ruby, PHP, Java, and .NET) configured correctly and not work properly when SSL certificates are invalid. Shmatikov, The most dangerous code in the world: Checking SSL certificates in software other than the browser shows how SSL checking is confused, so I want to thoroughly test possible failures.

Based on the research, the certificate is not valid if:

  • It is used until its activation date.
  • Used after expiration
  • Canceled
  • The hostname of the certificate does not match the hostname of the site
  • The certificate chain does not contain a trusted certificate authority

Ideally, I think I will have one test case for each of the invalid cases. To this end, I am currently testing an HTTP site accessed via HTTPS , which leads to an error that I can verify in the test, for example:

 self.assertRaises(SSLHandshakeError, lambda: api.call_to_unmatched_hostname()) 

This is incomplete (only coverage of one case) and potentially incorrect, therefore ...

How can you verify that non-browser software validates SSL certificates correctly?

+6
security ssl integration-testing testing
Jun 24 '13 at 15:50
source share
2 answers

First, you need a collection of SSL certificates in which everyone has something wrong. You can generate them using the openssl command-line tool. Of course, you cannot sign them with a trusted root certification authority. You will need to use your own CA. To verify this correctly, you need to install the CA certificate in the client libraries. You can do this in Java, for example, using the control panel.

Once you have the certificates, you can use the "openssl s_server" tool to serve the SSL socket using each of them. I suggest you put one certificate per port.

Now you need to use the client library to connect to the port and make sure that you get the correct error message.

I know that Python does not validate a certificate by default (see the httplib.HTTPSConnection manual). However, m2crypto does the check. Java performs validation by default. I do not know other languages.

Some other cases you might want to check are: 1) Wildcard names. 2) Chain of certificates. I know that there was a mistake in older browsers: if you have a certificate A signed by the root, A can then sign B, and B will be valid. SSL should stop this by having flags on certificates, and A will not have a "can sign" flag. However, this has not been verified in some older browsers.

Good luck I would be interested to know how you are doing.

Floor

+5
Jun 24 '13 at 17:27
source share
  • The hostname of the certificate does not match the hostname of the site

    This is probably the easiest way to verify, and failure (for failure) is certainly a good sign that something is wrong. Most certificates for known services use hostnames only to identify them, not IP addresses. If instead of requesting https://www.google.com/ you request https://173.194.67.99/ (for example) and it works, something is wrong.

For others, you can create your own CA for testing.

  • The certificate chain does not contain a trusted certificate authority

    You can generate a test certificate using your test CA (or a self-signed certificate), but let the default list of system CAs be used for verification. Your test client should not verify this certificate.

  • It is used before its activation date, it is used after its expiration

    You can generate test certificates using your test CA with notBefore / notAfter dates that invalidate the current date. Then use your CA to verify as a trusted CA for verification: your test client will not be able to verify the certificate due to dates.

  • Canceled

    This is probably the hardest to configure, depending on how the cancellation is published. Again, generate some test certificates that you immediately revoked using your own test certificate authority. Some tools expect them to be configured with a set of CRL files next to many trusted CAs. This requires some tweaking for the test itself, but very little online tweaking: this is probably the easiest. You can also set up a local revocation repository on the Internet, for example. using CRL or OCSP distribution points.

PKI testing can be more complex than more general. A complete test suite will require a fairly good understanding of the specifications (RFC 5280). Indeed, you may need to check the dates for all intermediate certificates, as well as different attributes for each certificate in the chain (for example, key usage, basic restrictions, etc.).

In general, client libraries divide the verification process into two operations: checking that the certificate is trusted (part of the PKI), and verifying that it was sent to the entity you want to connect to (part of the host name check). This, of course, is due to the fact that they are indicated in different documents (RFC 3280/5280 and RFC 2818/6125, respectively).

From a practical point of view, the first two points to check when using the SSL library:

  • What happens when connecting to a known host, but with a different identifier for which the certificate is not valid (for example, its IP address instead of the host)?
  • What happens when you connect to a certificate, which, as you know, cannot be verified by any standard set of trusted bindings (for example, a self-signed certificate or your own CA).

Inability to connect / verify should occur in both cases. If all this works, with the exception of implementing the full set of PKI tests (which requires some expertise), it often happens that you need to check the documentation of this SSL library to see how these checks can be included.

Mistakes aside, a significant number of the problems mentioned in this article are related to the fact that some library implementations have suggested that users should know what they are doing, while most of their users seem to have suggested that By default, the library did the right thing. (In fact, even if the default library does the right thing, of course, there is no shortage of programmers who just want to get rid of the error message, even if it makes their application insecure.) I would say, it’s fair to say that make sure verification functions are included, in most cases will be enough.

Regarding the state of several existing implementations:

  • Python: Python 2.x and Python 3.x have changed. The Python 3.2 ssl module has a match_hostname method that Python 2.7 does not have. urllib.request.urlopen in Python 3.2 also has the ability to customize CA files, which its Python 2.7 equivalent does not have. (However, if it is not installed, verification will not occur. I am not sure about the verification of the host name.)

  • Java: validation is enabled by default for both PKI and host name for HttpsUrlConnection , but not for the host name when using SSLSocket directly, if you are not using Java 7, and you configure its SSLParameters using setEndpointIdentificationAlgorithm("HTTPS") (for example) .

  • PHP: as far as I know, fopen("https://.../") will not perform any checks at all.

+4
Jun 24 '13 at 18:22
source share



All Articles