Certificate Pinning in a Mobile Application

Many times during our mobile application penetration testing, we are finding the applications are vulnerable to man-in-the-middle attacks (MITM). Certificate pinning is one part of the answer to MITM attacks in a mobile application. For those who do not know about certificate pinning, this is not pinning your CISSP certificate to the wall.

What is it?

Certificate pinning is hardcoding or storing the information for digital certificates/public keys in a mobile application. Since the predefined certificates are used for secure communication, all others will fail, even if the user trusted other certificates.

In a mobile application, the application knows what servers they will connect to, so that the application can check for those specific certificates. A browser cannot implement certificate pinning, since it is designed for general-purpose communication.

What happens during an SSL Connection?

When an application sees an SSL certificate from a server, it should verify two things:

  1. The certificate signed by a root certificate authority (CA)
  2. The server’s name (via DNS) matches the Common Name (CN) presented in the SSL certificate

In the case where these do not match, the application (or browser) throws up a warning and lets the user decide what to do. In many cases, the general user population will not understand the warning and just decide to accept the invalid certificate.

What are we trying to do by certificate pinning?

The idea is to prevent a man in the middle attack. This allows the attacker to get in the middle of the conversation between a client and server. They could be just eavesdropping on the conversation or could be changing the data as it moves to the client or server.

An attacker who gains control of a user’s operating system can install trusted root Certificate Authorities. These root CAs will be able to sign new certificates, which will satisfy SSL validation procedures. Certificate pinning prevents this by ensuring a specific server public key is used to initiate secured traffic.

How do we implement certificate pinning?

Distribute the server’s public key with the application. Any time the application begins an SSL exchange with the server, validate that the traffic has been encrypted with the same key that matches the public key included with the app. This takes the CA system out of the equation and assuming it is the correct certificate, the names do match.

Is there a way to break certificate pinning?

An attacker would have to decompile the application, change the code, rebuild it and redeploy the application. Another option would be to run the application in a debugger.

For Android, you can obfuscate your code. You can also check to see if the application is running in a debugger. Code signing will also make it more difficult for an attacker to create an unauthorized patch for your application.

For iOS, see Detecting the Debugger

For Android, see Securing Android LVL Applications

Neither of the above options are perfect, but they do help. Both of these methods make the attacker’s job harder, but not impossible.

Where else can I find information on this?

OWASP provides some information and sample code:

User Privacy Protection Cheat Sheet and Pinning Cheat Sheet

Moxie Marlinspike provides good information for an Android on his blog:

Your app shouldn’t suffer SSL’s problems

iSecPartners provides other information for iOS:

SSL Pinning on iOS

Discover why security operations teams choose NetSPI.