If you’ve ever had a security assessment conducted on a mobile application, whether it be on an iOS or Android device, you may have been advised to implement certificate pinning. However, what’s the real security impact of not implementing pinning within your application? In the next few sections we will take a brief look into what certificate pinning is, the circumstances in which it’s useful, and the security benefits and trade-offs of its use.
What is Certificate Pinning?
To understand the idea of certificate pinning, we must first discuss the concept of TLS, certificates, and Certificate Authorities.
TLS and Certificates
Transport Layer Security (TLS) is the successor to the deprecated Secure Sockets Layer (SSL) cryptographic protocol, both of which were designed with the aim to provide confidentiality, integrity, and authentication of application layer network communication. To achieve this, symmetric cryptography is used to encrypt network communication with the required secret being negotiated via asymmetric/public-key cryptography, and public-key cryptography also providing server authenticity.
The server usually presents its public-key to the client encapsulated in an X.509 certificate, X.509 being the standard defining the format of the certificate information. This is known as a leaf certificate, and binds the public-key to an identity along with containing the details required to provide assurance about the authenticity of the provided public-key. These details include a Common Name (CN) field (considered deprecated since RFC 2818 in 2000), and a Subject Alternate Name set which tie the public-key to specific hostnames, validity dates, and a cryptographic signature from a certificate issuer, known as a Certificate Authority (CA), who vouches that the certificate details are correct and the public-key belongs to the stated identity.
In order for the CA to vouch for the identity of the server, the CA maintains their own self-signed identity certificate called a root certificate, which in the interest of security is often only used to sign an intermediary certificate, which is finally used to sign any leaf certificates. This identity tree structure from root to leaf certificates forms the chain-of-trust model which is the basis of TLS.
For a client application on a mobile device to trust a leaf certificate is correct, the application will generally first trust a predefined set of ‘trusted’ CA intermediary/root certificates that are pre-installed in the mobile device’s Operating System (OS) trust store, or added during OS updates. During a TLS connection, the server will then typically provide not only its own leaf certificate, but a chain of certificates, each signed by the last, that lead back to one of these ‘trusted’ certificates.
It’s important to note that the server may send an arbitrary number of certificates in any order. Therefore, it’s the responsibility of the client to correctly construct and validate if a chain exists from the requested hostname to a trusted certificate. However, correctly validating the certificate chain by the client is not only critical for the security of TLS communication, but also complex and prone to error.
For an example, in 2011 it was found that Apple iOS did not check the Certificate Basic Constraints parameter, which states if the identity is or is not a CA, when validating certificate chains. This was given CVE-2011-0228 and would allow an attacker to generate a valid certificate for an arbitrary domain signed with the private-key of a valid non-CA certificate, and therefore have the ability to Man-in-the-Middle (MitM) the SSL communication to the domain. Due to this complexity, it’s strongly recommended not to roll your own certificate chain validation and instead consider the OS implementation or a well-tested third-party library.
So assuming that validation of the certificate chain has been implemented correctly by the client, and the ‘trusted’ CAs are trustworthy, TLS successfully provides the following:
- Confidentiality of application layer network traffic through the use of symmetric encryption,
- Integrity of the communication through the use of Message Authentication Codes (MAC), and
- Authentication of the identity of one or both of the communicating parties through the use of public-key cryptography and the chain-of-trust.
However, the inherent trust of the Certificate Authorities is an unavoidable weakness of TLS; what happens if one of them is compromised? In that scenario, a valid certificate for any hostname could be produced by the attacker and signed with the compromised CA’s private-key, allowing the ability to MitM the communication of any TLS connection. In addition, the trust store of a user’s mobile device may be compromised to add a CA certificate owned by an attacker, resulting in the same outcome. This is where the idea of certificate pinning comes in.
The problem that TLS attempts to solve is a world where the client does not necessarily know the identity of the server, hence trusts a CA to vouch for the server’s identity, and is therefore vulnerable to CA mistakes and compromise.
Certificate pinning is a technique first proposed for HTTP by Evans and Palmer in 2011, in which the server could instruct the user-agent to pin (store) the server’s public-key for a period of time. During that time, subsequent visits to the server would allow the presented SSL/TLS certificate to be validated against the pinned value, limiting the number of CAs that could authenticate the domain, and reducing the incidence of MitM attacks due to CA mistakes or compromise.
This technique has since been deprecated in Chrome due to the risk of denial-of-service (DoS) and hostile pinning attacks, however the concept of certificate pinning is still valuable for mobile applications where the identity of the back-end server is often known in advance to the developers, and the expected value that is pinned can be hard-coded into the application.
This concept compliments the chain-of-trust to a ‘trusted’ CA by ensuring a known certificate exists within the chain. There are a few ways that this might be implemented, however a general implementation will either:
- pin the leaf certificate of the expected host, or its public-key, or
- pin a specific root or intermediary certificate, or its public-key.
For example, a mobile application that communicates with a back-end server via TLS may have the server’s expected TLS public-key hard-coded. When the server provides its certificate to the client mobile application, the application can, in addition to validating the certificate chain, also validate that the public-key within the certificate matches that of the hard-coded public-key. In the event an attacker has compromised a CA’s private-key and created a new certificate for the hostname, the certificate chain will be valid, however the public-key within the leaf certificate will be a different value to what was expected, and therefore should be rejected by the application.
What’s the likelihood of a compromised CA?
Compromising a CA may seem like a difficult task, and it definitely should be. However, take a quick look at the trusted certificates included in a mobile device’s trust store, for example the pre-installed trusted certificates in iOS 12, and you will see quite a long list. Do you know who they are? Some are government organisations, some are relatively small organisations. How much do you trust them? How much do you trust that none of them have been compromised?
Mistakes and compromised CAs do happen. For example, in 2011 the Dutch CA DigiNotar was compromised, in which a fraudulent SSL certificate for *.google.com was issued. It’s worth noting here that the fraudulent certificate was detected by Google Chrome users, as Google was utilising certificate pinning within their browser to whitelist specific CAs.
Some more recent examples include, in 2017 it was reported that Symantec had issued a number of certificates without proper validation, and in 2018 it was reported that the private-keys for a large amount of certificates were leaked, as can be seen in the headline below.
In addition, when thinking about a potential MitM attack, people tend to only consider the scenario in which the attacker is intercepting communication between the client and the server from the client end, as shown in the diagram below.
However, consider when the attacker can actively MitM communication between the server and CA, as below.
In this scenario, the attacker wants to MitM the traffic between the client and server, so they request a certificate from a CA with the desired domain. The CA must obtain proof of control of the domain, so it typically issues a challenge through some method of Domain Control Validation (DCV). If a HTTP-based DCV is performed, such as the method offered by Let’s Encrypt and many other CAs, then the attacker may intercept the challenge, sign it with their own private-key, and send it back to the CA as if returned by the legitimate server. With control ‘proven’, the CA will issue the attacker a valid certificate containing the attacker’s public-key, establishing a valid certificate chain to a ‘trusted’ CA, and allowing the attacker to MitM the client/server communication in the normal fashion. As you can see, TLS only protects the client half of the communication problem and is another example where certificate pinning may offer some protection.
If anything, history shows us that CA issues do occur, and compromise may not be that far-fetched. More importantly though, how much do you care in regard to your own mobile application?
To pin, or not to pin?
Regardless of the data you communicate, it’s a good idea to implement TLS for your application. First and foremost, the concern for a developer should be that TLS has been implemented correctly using mature, maintained, and up-to-date libraries, and ensuring that certificate chains are properly cleaned and validated. Following that, certificate pinning may be considered as a defence-in-depth strategy.
It might help to consider the following when determining if pinning should be implemented:
- How sensitive is the information your application is communicating?
- How concerned are you about CA compromise in the context of your application?
- Is your organisation mature enough to handle the operational overhead?
Although implementing pinning may seem like an ideal choice for your application, it’s operational use can come with some additional headaches. This is where ideals must be weighed against practicality, so let’s now take a brief look at the benefits and trade-offs of implementing certificate pinning.
If implemented correctly, certificate pinning can offer the following benefits:
- reduced attack surface for remote MitM attacks,
- better protection against a rogue or compromised CAs,
- better protection against CA mistakes,
- better protection against malicious certificates added by the user,
- may slow down reverse engineering (RE) of the application communication, and
- may hinder unprivileged malware on the device.
On the contrary, certificate pinning:
- does not provide confidentiality or integrity of the network communication – TLS does,
- does not protect against compromise of the pinned certificate’s private-key – forward secrecy does,
- does not protect in the case of a rooted/jailbroken device,
- does not prevent RE – code signing may be more suited.
Operationally there are also some concerns with certificate pinning that need to be thought about. For example, it’s more difficult to change the certificate if it has been pinned as this will usually involve having to issue an update for the mobile application. In addition, the pinned certificate is likely now a single point of failure for the system. Are users who haven’t updated the application then denied service?
A few other operational aspects to think about are as follows:
- how will private-keys be safely stored?
- how will a compromised pinned certificate be handled?
- how will a primary server loss be handled?
- how will a CA change, certificate change, or private-key rotation be handled?
- how will pinned certificates be deployed?
- how will certificate pinning affect compatibility?
- how will communication to third-party servers be handled? (i.e. analytics, advertising, crash reporting, etc.)
- how will you be notified if the pinning breaks? (i.e. your app cannot report it to your server)
- how will your non-production environments work? (i.e. will you pin a different certificate or a separate configuration/configurator to disable pinning?)
- how will users who don’t update, or cannot update their application be affected? (i.e. their OS version is no longer supported)
As you can see, pinning might be an ideal defence-in-depth measure from a security perspective, but also adds a bunch of operational processes and problems that must be dealt with.
For those that pin
If you’ve decided to implement certificate pinning, similar to TLS, it’s easy to get a custom implementation wrong and it’s recommended to instead consider the OS implementation, such as the Android network security configuration, or a well-tested third-party library.
In either case, it’s advisable to ensure the following:
- the certificate chain is still validated,
- the checked pin is in a valid certificate chain,
- that only certificates on your chain are pinned,
- that all pins map to their expected domains,
- that all important hosts are pinned, and
- pin validation occurs for all new connections
Backup pins can be implemented in case of compromise or loss, however keep in mind this extends the attack surface, and therefore the security offered is then only as good as the least secure pin. Ideally, the backup pin should give the same security guarantees as the original pin.
For further information on issues and examples of bad implementations of certificate pinning, I highly recommend watching the presentation Pinning: Not as simple as it sounds by John Kozyrakis.
Is the lack of pinning a vulnerability?
Now getting back to the original question of this post; is the lack of certificate pinning in your mobile application a legitimate vulnerability? I would argue that a vulnerability does exist without it, as a compromised ‘trusted’ CA would allow remote MitM of the TLS communication. However, the likelihood and impact of that vulnerability being exploited for your application really depends on the sensitivity of the information being communicated, and the threats that your application needs to address. We generally accept the risk of CA compromise as far as our daily browsing is concerned, so does your mobile application require further security guarantees?
In any case, if you’ve decided to implement certificate pinning in your application, any of the following issues should be considered a vulnerability:
- the implementation of certificate pinning is broken,
- pinning can by bypassed remotely (i.e. not from the mobile device itself), or
- the pinning implementation breaks TLS.
This blog post took a brief look at TLS, certificates, and CAs, along with an overview of certificate pinning, and the problem of trust in CAs that it addresses. Whether the trust of CAs is a real concern and certificate pinning should be implemented in your mobile application really comes down to the sensitivity of the information being communicated, and the likely threats to your particular application. In either case, the correct implementation of TLS should be the first priority, with certificate pinning ideally implemented as a defence-in-depth measure.
The reality of implementing certificate pinning comes with its own issues however, and the security benefits must be weighed against the additional operational burden and practicality. For those that implement certificate pinning, it’s important that this does not break the security that is provided by TLS. A certificate pinning implementation that breaks TLS, is broken, or remotely bypassable, should be considered a security vulnerability.