4

Scenario :

  • I have pinned public key pin SHAs of 3 certificates : Root CA , Intermediate CA and Leaf CA in my android application.

What I have understood ( Please correct me if I'm wrong anyway here ) :

  • Public key pinning is used so that we can check if the public key of the cert that our server is issuing is changed or not. source

  • A certificate is valid if its public key SHA is the one which we have "pinned" in our application. To check the public key , first it will decrypt the signature using the public key and makes sure that the same public key is in the data of that signature also.

  • When the Leaf cert has expired but is corresponding to the valid "pinned" public key SHA, the chain of certificates is checked to see if they are valid and if one of them is valid , the certificate is accepted and the connection is established.

  • When the Leaf cert I got is having an invalid public key but is not expired , then that means I got a wrong certificate from someone which may be an attacker.

Question :

  • Does public key pinning in any way help in security , if an attacker compromises a client and installs his own trusted CA and then does an MITM on the client to intercept all communication by presenting his own forged certificate signed by the CA he has installed on the client device.

  • How does direct certificate pinning VS public key pinning make a difference here in any way ?

  • What is the implication of using a self signed certificate in the above questions.

Please help me understand this with as much detail as possible...

Natesh bhat
  • 12,274
  • 10
  • 84
  • 125

2 Answers2

3

When the Leaf cert has expired but is corresponding to the valid "pinned" public key SHA, the chain of certificates is checked to see if they are valid and if one of them is valid , the certificate is accepted and the connection is established.

No. An expired certificate is not accepted. Pinning does not override that basic principal of TLS but enhances it to reduce the number of certificates accepted.

Does public key pinning in any way help in security , if an attacker compromises a client and installs his own trusted CA and then does an MITM on the client to intercept all communication by presenting his own forged certificate signed by the CA he has installed on the client device.

For browsers, manually installed trusted CAs are exempt from pinning requirements. To me this is a fundamental flaw in pinning. Though to be honest once you have access to install root certs on a machine it’s pretty much game over. Anyway, this exception is necessary to allow Virus scanners, Corporate proxies and other intercepting proxies to work - otherwise any pinned site could not be accessed when behind one of these proxies though it does weaken HPKP (HTTP Public Key Pining) in my mind.

For apps (your use case) pinning can be useful to prevent MITM attacks.

How does direct certificate pinning VS public key pinning make a difference here in any way ?

Don’t understand? When you pin a direct certificate you basically pin the public key of that certificate (well actually the SHA of the private key that cert is linked too).

This means you can reissue the certificate from same private key (bad practice in IMHO) and not have to update pins.

You can also pin from the intermediate or even root public key. This means you can get your CA to reissue a cert and again not have to update the pin. That of course ties you into that CA but at least doesn’t allow some random CA to issue a cert for your site.

What is the implication of using a self-signed certificate in the above questions.

For browsers, pinning basically can’t be used with a self-signed cert. because either it’s not recognised by browser (so pining won’t work) or its is by trusting by manually installing the issuer - at which point pinning is ignored as per point above.

For apps (again your use case), I understand self-signed certificates can be pinned. Though it depends on which HTTP library you use and how that can be configured.

One of the downsides of pinning the certificate itself (which might be the only way to do it, if it's a single leak self-signed certificate), is that reissuing the certificate will invalidate the old pins (unless you reuse the same private key but this may not be possible if the re-issue reason is due to key compromise). So if you app makes an HTTP call home to check if there is a new version or such like, then that call might fail if certificate is re-issued and new version of the app has not been downloaded yet.

Nearly browsers have deprecated HPKP as it was massively high risk compared to the benefits and there were numerous cases of breakages due to pinning. See Wikipedia: https://en.m.wikipedia.org/wiki/HTTP_Public_Key_Pinning. Monitoring for mis-issued certificates through Certificate Transparency is seen as a safer option.

Pinning still seems somewhat popular in mobile app space because you have greater control over an app and can re-release a new version in case of issues. But it is still complicated and risky.

Barry Pollard
  • 40,655
  • 7
  • 76
  • 92
  • "Pinning basically can’t be used with a self-signed cert. because either it’s not recognised by browser". What about mobile applications ? – Natesh bhat Jun 05 '20 at 06:36
  • in a mobile app we pin the public key SHAs of all the certs from root to leaf. Can u please update your answer regarding the implications in relation to a mobile app ? – Natesh bhat Jun 05 '20 at 06:37
  • Sorry I missed the fact this was for an App and not for browsers. Answer updated. – Barry Pollard Jun 05 '20 at 16:30
  • @Barry Pollard if I understood correctly, for mobile apps, if I pin only the root public key SHA instead of all 3 public keys SHA it will still work, because even if the leaf and intermediate pins are missing because of the chain of trust will see that the root pin is matching so will work? – Claudiu Jul 22 '20 at 12:13
  • Regarding manually installed trusted CAs for corporate proxies: what was the reason for disabling HPKP validation in browsers? Doesn't corporate CAs need to be protected from compromising? – Alex Buchatski Dec 20 '20 at 18:45
1

My Answer Context

Scenario :

I have pinned public key pin SHAs of 3 certificates : Root CA , Intermediate CA and Leaf CA in my android application.

My answer will be in the context of pinning in a mobile app. anyway the new browsers don't support pinning any-more.

Pinning and Security

Does public key pinning in any way help in security

It helps a lot, because your mobile app only communicates with a server that presents the certificate with a matching pin. For example, if you do public key pinning and you rotate the certificates in your backend while signing it with a different private/public key pair then your mobile app will refuse to connect to your own server until you release a new version of the mobile app with the new pins.

MitM attack and Pinning

if an attacker compromises a client and installs his own trusted CA and then does an MITM on the client to intercept all communication by presenting his own forged certificate signed by the CA he has installed on the client device.

When you are pinning the connection the attacker will not succeed, because this is for what pinning was designed for, to protect against manipulation of the certificates trust store on the device in order to carry on a MitM attack. From Android API 24 user provided certificates are not trusted by default, unless the developer opts-in to trust on them via the network security config file:

<base-config cleartextTrafficPermitted="false">
    <trust-anchors>
        <!-- THE DEFAULT BEHAVIOUR -->
        <certificates src="system" />

        <!-- DEVELOPER ENABLES TRUST IN USER PROVIDED CERTIFICATES -->
        <certificates src="user" />
    </trust-anchors>
</base-config>

You can read the article I wrote to see pinning in action and not allowing for a MitM attack to succeed:

In order to demonstrate how to use certificate pinning for protecting the https traffic between your mobile app and your API server, we will use the same Currency Converter Demo mobile app that I used in the previous article.

In this article we will learn what certificate pinning is, when to use it, how to implement it in an Android app, and how it can prevent a MitM attack.

In the article I go into detail how to implement pinning, but nowadays I recommend instead the use of the Mobile Certificate Pinning Generator online tool, that will generate the correct network security config file to add to your Android app. For more details on how to use this tool I recommend you to read the section Preventing MitM Attacks in this answer I gave to another question where you will learn how to implement static certificate pinning and how to bypass it:

The easiest and quick way you can go about implementing static certificate pinning in a mobile app is by using the [Mobile Certificate Pinning Generator](Mobile Certificate Pinning Generator) that accepts a list of domains you want to pin against and generates for you the correct certificate pinning configurations to use on Android and iOS.

Give it a list of domains to pin:

Config tab on the mobile certificate pinning generator web page

And the tool generates for you the Android configuration:

Android certificate pinning configuration

The tool even as instructions how to go about adding the configurations to your mobile app, that you can find below the certificate pinning configuration box. They also provide an hands on example Pin Test App for Android and for iOS that are a step by step tutorial.

This approach will not require a release of a new mobile app each time the certificate is renewed with the same private/public key pair.

Certificate Pinning vs Public Key Pinning

How does direct certificate pinning VS public key pinning make a difference here in any way ?

When using certificate pinning a new mobile app needs to be released and users forced to update each time the server certificate is rotated, while with public key pinning no need for this unless the private/public key pair used to sign the certificate changes. For example, if your server uses LetsEncrypt for the certificates you don't need to release a new mobile app version each time they are renewed.

Self Signed Certificates

What is the implication of using a self signed certificate in the above questions.

You will need to opt-in via the network security config file for the Android OS to trust in user provided certificates and instruct the user to add it to his mobile device. This will make an attacker life easier if pinning is not being used. I would recommend you to stay away of using self signed certificates.

Exadra37
  • 11,244
  • 3
  • 43
  • 57
  • I wonder, why you don't promote the [alternative approach](https://www.youtube.com/watch?v=bHYZl1IC9SE) which does not require *pinning* the cert, but (if I understand correctly) lets the *server* know which certificate is being used, and delegates the trust/no-trust decision to the protected side of the dialog? – Alex Cohn Dec 05 '21 at 19:52
  • The alternative approach does require to pin the public key of the certificate, like the one mention in this reply. The difference is that the alternative approach you linked doesn't require the developer to code it and the pinning configuration is dynamic, (allows to update the pins remotely). Also, the certificate being used is always provided by the API server, not by the mobile app. You may be confused with mutual TLS authentication where both sides need to present a certificate that the other side trusts on. – Exadra37 Dec 06 '21 at 11:27
  • The usecase is when the certificate is managed by a cloud provider. E.g. you cannot really "pin" a certificate of a GCP Load Balancer. But if the backend knows which certificate was presented to the client app, it can verify that no MITM attack is underway. – Alex Cohn Dec 06 '21 at 12:06
  • You are failing to understand how pinning works when you say that if the backend knows the certificate then it can detect a MitM attack. First the backend cannot detect a MitM attack in this context, second the certificate presented is always the one for the domain of the backend or for whatever does the TLS termination. The method described pins the leaf certificate public key by default, but you can pin the root certificate on the chain presented by the API server, because the root certificate doesn't change often, or if you can/prefer you can pin the intermediate certificate in the chain. – Exadra37 Dec 06 '21 at 14:55
  • thanks, it's more clear now – Alex Cohn Dec 06 '21 at 16:27