Friday, October 23, 2015

A certificate revocation security vulnerability in Java

A few days ago, Oracle released a Critical Patch Update containing fixes for various security vulnerabilities. In particular, the update contained fixes for 25 security vulnerabilities in Java itself. One of them, CVE-2015-4868, was discovered by me and duly disclosed to Oracle earlier this year. This issue has now been fixed in this Critical Patch Update (and included in Java 1.8.0_65), and so I am free to describe it.

1) Background

I first noticed this issue in the context of signature validation of SOAP web service requests. A signed SOAP request involves using XML Signature to sign some part of the request, where the resulting Signature structure is inserted into the security header of the request. The Signature contains a KeyInfo Element, which references the (public) key to use to validate the request. The recipient must resolve the appropriate public key, establish trust in it, and use it to validate the signature.

A common use-case is when the certificate used to validate the signature is included directly in the request, by BASE-64 encoding it in the security header. Optionally, the full certificate chain can be included instead. The recipient must take the certificates and establish a trust chain using a CA certificate stored in a local truststore, which is then validated.

However, what if the signing certificate has been revoked by the issuing CA? In this case, we can specify a Certificate Revocation List, and include it as part of the validation of the trust chain.

2) The vulnerability

Now to the vulnerability. Under the more usual use-case of just including the signing certificate in the security header, and establishing a trust-chain using a local truststore and CRL file, everything was working fine. Namely, if the signing certificate was trusted, but revoked, then the CertPath validation failed. However, if the issuing certificate of the signing certificate was also included in the security header, then CRL validation was not failing! This vulnerability exists in a range of JDK 8 versions prior to 1.8.0_65. It does not exist prior to JDK 8.

To see how this works using the Java CertPathValidator API, I created a simple maven-based unit test in github:
  • java.crls - A testcase that show how to include a CRL when validating the certificate path of a certificate.
The test has a JUnit failure assertion that asserts that the CertPathValidator validation should fail (as the signing certificate has been revoked). However, this failure assertion is not met when run locally with Java 1.8.0_51. With a Java version post-1.8.0_65 the failure assertion is met, and the test passes.

No comments:

Post a Comment