2

I am implementing SSL pinning as a security requirement for a project and the HTTPS endpoint is giving me SslPolicyErrors. The following errors occur,

RemoteCertificateChainErrors
    RevocationStatusUnknown
    UntrustedRoot

This only occurs for our QA endpoint and not our PROD endpoint so I think there could be an issue with the certificate. Both have a certificate chain.

If I ignore these issues and just check that the public key certificate.GetPublicKeyString () matches, will that be secure, or will hackers be able to spoof our certificate because we are not checking the chain?

Here's the code that checks for SslPolicyErrors that I am considering removing.

if (sslPolicyErrors != SslPolicyErrors.None) {
    Debug.Log(sslPolicyErrors);

    for(int i=0; i<chain.ChainStatus.Length;i++){
        Debug.Log("-");
        Debug.Log(chain.ChainStatus[i].Status);
        Debug.Log(chain.ChainStatus[i].StatusInformation);
    }
    return false;
}

Here's the sample .NET code from OWASP.

ServicePointManager.ServerCertificateValidationCallback = PinPublicKey;

-

    public static bool PinPublicKey(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
        if (certificate == null || chain == null)
            return false;

        if (sslPolicyErrors != SslPolicyErrors.None)
            return false;

        // Verify against known public key within the certificate
        String pk = certificate.GetPublicKeyString();
        if (pk.Equals(PUB_KEY))
            return true;

        return false;
    }
2

TL;DR yes it is safe provided that you trust the means by which you came across the value stored in PUB_KEY.

Here is some background that is needed to first understand the purpose of pinning, and why your scenario allows for ignoring of the error. I'll concentrate specifically on PKI in an ideal implementation.

A private key is a very, very large number that meets certain mathematical criteria. With said private key it is possible to derive a specific public key, but the reverse process is so computationally expensive that it can be considered impossible.

"Applying" a public key to data is "undone" by subsequent application of the associated private key, and vice versa. The owner of a private key can thus freely publish their public key in order to receive messages that, for all intents and purposes, only they can read. Conversely they may publish "signed" data that has had their private key "applied"; this allows recipients to be assured that the data was published by the owner of the private key by checking that "undoing" the signature results in the same data.

This process is all well and good as long as parties to communication are knowledgeable of the ownership of public keys. In such a situation communications proceed as follows:

A -> B
B -> A

However an adversary may exploit the lack of knowledge regarding the true ownership of public keys to act as a "man in the middle" (MITM) by falsely claiming to be the expected recipient:

A -> E -> B
B -> E -> A

A and B are none the wiser. This is where the root certificate comes into play. The root certificate is owned by a trusted third party called a certificate authority (CA) who (i) verifies the owners of respective public keys, and then (ii) uses their own private key (linked to the root certificate) to sign a message to the effect of "Person (A|B) owns public key (X|Y)". A and B, already knowing the public key of the CA can verify that the signature is valid. E can now no longer impersonate A or B without compromising the CA.

The CA's public key is known to A and B through means other than the untrusted network on which they communicate. In the event that A and B are already knowledgeable with regards to the other's public key then the need for the CA is obviated; this is key pinning.

You have "pinned" the public key of your server endpoint by hard-coding it into the value of PUB_KEY.

CAs may publish revocation lists to the effect of "I said that A owns public key X but you should now ignore that" (e.g. if the private key is compromised) and the 'RevocationStatusUnknown' error speaks to that effect.

The 'UntrustedRoot' error says that whomever is acting as the CA in this case is not truly trusted. Who is trusted, and how their keys are distributed is beyond the scope of this answer.

2

A trusted root is only relevant if you need to validate the trust chain of the certificate until you get the root. If you only expect a specific certificate or public key there is no need to check any chains and in lots of cases there is no trust chain anyways (i.e. self-signed certificates).

In case of revocation you might actually add an URL to the certificate where the client can get the CRLs from or where it can send OCSP queries too and thus have a way to even revoke pinned certificates. But this will probably not work with self-signed certificates because OCSP responses and CRL needs to be signed by the issuers CA (or some other CA trusted for this purpose) and in case of self-signed certificates the issuers certificate is the one you want to check the revocation status for, which would not make sense.

You might actually have a look at the OWASP information about pinning which comes with code samples on how to implement pinning properly.

  • Thanks for the information about this. I've actually used the sample code(.NET sample program) on OWASP to create my SSL pinning code. They have the sslPolicyErrors check in their sample code. It sounds like it might not be needed though – sissonb Apr 17 '15 at 19:04

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.