Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}
Refcard #285

Securing Mobile Applications With Cert Pinning

Securing your mobile applications with cert pinning will help you ward off man-in-the-middle (MiTM) attacks, verify users using trusted certificates, and secure HTTPS network traffic. In this Refcard, you’ll learn about what MiTM attacks are, how to implement cert pinning on both iOS and Android apps, and how to test and maintain your certificate pinning.

2,633
Free .PDF for easy Reference

Written by

Rono Dasgupta Mobile Security Analyst, NowSecure
Refcard #285

Securing Mobile Applications With Cert Pinning

Securing your mobile applications with cert pinning will help you ward off man-in-the-middle (MiTM) attacks, verify users using trusted certificates, and secure HTTPS network traffic. In this Refcard, you’ll learn about what MiTM attacks are, how to implement cert pinning on both iOS and Android apps, and how to test and maintain your certificate pinning.

2,633
Free .PDF for easy Reference

Written by

Rono Dasgupta Mobile Security Analyst, NowSecure
Table of Contents

MiTM Attacks

Why and When to Use Cert Pinning

Types of Certificates

Implementing Cert Pinning on iOS and Android

Testing and Maintenance

Countering Objections

Conclusion

Section 1

MiTM Attacks

As virtually all mobile apps communicate with backend systems that require secure network communications, mobile app developers should adopt best practices for secure architectural design and coding techniques.

Man-in-the-middle (MiTM) attacks are essentially a form of digital eavesdropping that exploit a weakness in network communication. They occur when a malicious third party gets between a user’s mobile app and the backend server the device attempts to communicate with. The threat actor can intercept, read, and alter data sent between the two parties.

And worse, a variety of different kinds of MiTM attacks means developers must use multiple techniques to protect their apps. But it’s fairly easy for developers to take a few coding measures to guard against these threats when you fully understand how to code them.

Image title

All mobile app developers should use HTTPS for secure communication. MiTM attacks. however, are remote in nature and present tremendous risk to a mobile app user’s personal data because they nullify the confidentiality and integrity provided by HTTPS.

Despite a common misconception, mobile app MiTM attacks don’t only happen over unsecured Wi-Fi at the local coffee shop. In fact, any network device can be used to intercept traffic and the attacker doesn’t need to be in the same room or even on the same network. For example, a virtual private network (VPN) provider could force users to install and trust a malicious root certificate on their devices to gain full access to decrypt network communication.

Hackers can carry out MiTM attacks in many ways, such as using misconfigured self-signed certificates with weak private keys, fake Wi-Fi login portals, e-mail attachments, and free virtual private networks.

How MiTM Attacks Ensnare Users

Thanks to social engineering and phishing, some users can easily be convinced to make changes to their mobile devices to make them susceptible to a man-in-the-middle attack. The attacker’s weapon of choice is a malicious iOS profile or Android certificate.

Say someone visits a conference venue and urgently needs to connect to Wi-Fi. The user attempts to connect to a Wi-Fi SSID that was broadcast with a name similar to the legitimate access point. After being redirected to a captive portal that looks authentic, the user is instructed to download and install a device profile. A captive portal web page requires a user to enter information or accept terms after connecting with a Wi-Fi network before being granted access. These are commonly seen at coffee shops, hotels, and airports.

If a victim ignores vague and innocuous security warnings and installs the profile, the attacker gains access to network traffic and can decrypt nearly everything sent and received by the mobile device.

iOS Attacks With Malicious Profiles

On iPhones, those with iOS profiles can create custom configuration settings on the device. Network administrators commonly use this method to efficiently set up secure W-Fi access or VPNs on employee devices. Apple makes it easy to build custom iOS profiles with the free Apple Configurator 2.

Apple Configurator 2 allows you to add several settings to the profile including:

  • Custom certificates for installation

  • Network settings (e.g. what wireless network the device should join automatically)

  • Proxy settings

  • VPN settings

Here’s a screenshot of the tool’s UI:

Image title

Image title

You can see that the profile, in this case, is marked “not signed,” but an attacker can easily sign the profile using a code-signing certificate.

The malicious profile presented to the user contains a self-signed certificate. The certificate needs to be self-signed for the device to install it as a root CA. Clicking on “Install” takes the user to a page that warns the user that installing the certificate will add it to the list of trusted certificates on their device (see screenshot below). This warning clearly fails to convey the actual danger of installing the certificate — that network traffic could be compromised.

Image title

Once a user installs the profile, which adds the certificate to a device’s list of trusted certificates, an attacker that is able to redirect all network traffic through their proxy can basically decrypt all the HTTPS traffic sent and received by the device. From the attacker’s perspective, carrying out this kind of MiTM attack required very little time or effort.

Android Attacks via Rogue Certs

While profiles don’t exist for Android devices, an attacker could still trick an unsuspecting user into installing certificates onto the device using similar techniques. An Android user has to install the certificate manually using the device’s security settings by going to “Credential storage” and tapping “Install from storage.” The user then has to select the downloaded certificate file in the .cer format and install it.

Note that, by default, apps don’t work with user-installed CA certificates on Android 7.0 and up. Trusted credentials are now divided into two sections: user and system. Only system CAs are trusted by default. This provides a fantastic security feature that all platforms should adopt in the near future.

App developers can choose to let their apps work with manually added CA certificates, but they must understand the security ramifications of doing so. Also note that Android P only supports HTTPS for all network communication by default. Any HTTP endpoints must be explicitly defined in the Network Security Configuration file.

Section 2

Why and When to Use Cert Pinning

Cert pinning is a security mechanism in which an app developer specifies certain trusted certificates used to verify the identity of computers on the network(s).

Android and iOS devices are shipped with a default list of trusted root certificate authorities (CA) pre-installed by the manufacturer. Apps can make use of these trust stores to verify if a certificate presented by a server can be trusted, a process termed certificate validation or verification.

Certificate pinning goes one step further and “pins” the certificates a mobile app trusts (i.e. only trusts certificates explicitly specified by the app) while rejecting certificates presented by an untrusted server. This halts the connection at the network layer and, in turn, prevents sensitive information from being leaked over the network. While stopping the mobile app function may inconvenience the mobile user, the hard-stop scenario is preferable to allowing data to fall into the hands of an MiTM attacker.

As a crucial first step in securing HTTPS network traffic, certificate validation prevents communication from being established if a server presents self-signed certificates or trusted certificates that are signed for a different hostname. Certificate validation with hostname validation stops most MiTM attacks from being successfully executed.

However, an attacker could leverage more sophisticated MiTM techniques. For example, users could be convinced to install a malicious root certificate on their devices using phishing techniques or the hacker could compromise a certificate authority itself. While the latter is difficult, getting a user to install a malicious root certificate can be surprisingly simple. When a user trusts a certificate, the device alert doesn’t convey the actual danger and many users simply click to accept as a force of habit.

Certificate pinning was originally developed to protect web and mobile apps from rogue certificate authorities. Pinning ensures that no network data is compromised even if a user is tricked into installing a malicious root certificate on their mobile device. Any app that pins its certificates would thwart such phishing attempts by refusing to transmit data over a compromised connection.

Launching an MiTM attack by bypassing certificate pinning is a very complex client-side procedure. An attacker would first need physical access to the targeted mobile device and app. From there, he or she would need to root or jailbreak the device and reverse engineer, modify, and rewrite the functions performing cert pinning in the app. In the end, bypassing certificate pinning is much more difficult than executing the type of attacks certificate pinning guards against.

As part of good coding hygiene, all Android and iOS developers should implement certificate pinning for apps that handle sensitive data as a countermeasure against MiTM attacks. This minimal degree of additional effort yields significant protection. However, developers must be sure to implement pinning correctly so they’re not left with a false sense of security.

Cert pinning is imperative for any mobile app that exchanges sensitive data like credentials, financial information, business transactions, and PII. This includes mobile apps such as banking, healthcare, retail, utility, automotive, ERP/CRM, and IoT. In short, this encompasses most apps that do anything more than surface public data.

Section 3

Types of Certificates

There are three types of certificates for an app to pin to:

  1. The CA as mentioned above

  2. An intermediate certificate

  3. A leaf certificate

Mobile apps that pin to the CA place a lot of trust in that CA by accepting any certificate for the domain in question signed by that CA using a root certificate. The root certificate is the be all, end all at the top of the certificate chain of trust.

Security and validation practices for issuing certificates can vary from CA to CA. Several CAs have been breached in recent years with bogus certificates created as a result. A threat actor could use a certificate issued by the same CA and hijack the connection. Combining this approach with a lack of hostname validation seriously weakens the security of an app’s host connections.

Pinning to an intermediate certificate is a step down in the hierarchy from the root certificate mentioned above, but has similar problems. The certificates at the bottom of the chain of trust — leaf certificates — can be signed using an intermediate certificate. In that event, a malicious individual can procure a certificate for the domain in question signed by an intermediate certificate and hijack the connection because his certificate will be trusted by the app.

Finally, pinning the public key of the actual leaf certificate is the best option and we recommend choosing this over the other methods. Every certificate includes a public key associated with the private key, which can be pinned within the app. This approach ensures the app trusts only signed certificates that an attacker cannot spoof.

Some people complain that the above method makes rotating expired keys a hassle and are tempted to take shortcuts like pinning to CA rather than leaf or avoiding cert pinning altogether. However, there are ways to properly implement a certificate rotation without having to release new versions of the app when certs expire and need to be swapped out.

Image title

To rotate certificates without any interruption in service, use cert pinning based on the modulus of the public key. This represents a unique identifier for the private key. Compare the public key modulus and the private key modulus to ensure the app trusts the proper certificate (or more importantly, doesn’t trust any other certificates).

Cert pinning using the modulus allows you to renew the public key and swap it out as long as the private key doesn’t change. Include two modulus signatures in the app — one for active use and one for one for future use with the private key stored offline. The following OpenSSL commands can be used in the terminal to check the modulus of the cert, depending on the cert extension (.pem, .cer, .crt, .der):

openssl x509 -in cert.pem -text -noout
openssl x509 -in cert.cer -text -noout
openssl x509 -in cert.crt -text -noout
openssl x509 -in certificate.der -inform der -text -noout
Section 4

Implementing Cert Pinning on iOS and Android

Pinning the public key of the leaf certificate is generally the best approach because it’s easy to manage when the server certificates change. To do this, pin the leaf certificate based on the modulus of its public key, which represents a unique identifier for the private key.

Comparing the public key modulus and the private key modulus enables you to ensure the app trusts the correct certificate (or, more importantly, doesn’t trust any other certificates). Pinning using the modulus allows you to renew the public key and swap it out as long as the private key doesn’t change. Include two modulus signatures in the app — one for active use and for future use, with the private key stored offline.

Android

Manual methods for deploying certificate pinning on Android apps include making HttpsURLConnection only trust a certain set of CAs. For more details about this manual method, see the OWASP Certificate and Public Key Pinning Technical Guide.

The Android Developer website describes a newer technique for certificate pinning on Android, which involves providing hashes of certificates’ public keys along with backup keys in an app’s res/xml/network_security_config.xml file. Backup keys help maintain app usage if and when the CA being pinned or the keys themselves have to be changed for some reason. If you don’t include backup keys, you will be forced to update your app in such cases.

The following snippet from the Android Developer site shows the res/xml/network_security_config.xml file.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">example.com</domain>
        <pin-set expiration="2018-12-17">
            <pin digest="SHA-256">7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=</pin>
            <!-- backup pin -->
            <pin digest="SHA-256">fwza0LRMXouZHRC8Ei+4PyuldPRcf3UKgO/04cDM1oE=</pin>
        </pin-set>
    </domain-config>
</network-security-config>

You can use a number of third-party libraries to implement certificate pinning in your Android apps. The popular Android library OkHttp is widely used for this purpose through its CertificatePinner class. The next three code snippets from the OkHttp website illustrate the process.

String hostname = "<domainname.com>";
     CertificatePinner certificatePinner = new CertificatePinner.Builder()
         .add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
         .build();
     OkHttpClient client = OkHttpClient.Builder()
         .certificatePinner(certificatePinner)
         .build();

     Request request = new Request.Builder()
         .url("https://" + hostname)
         .build();
     client.newCall(request).execute();

The code snippet above deliberately includes a false SHA256 hash value to simulate a broken configuration, so it will throw an exception (the output shown in the snippet below). Looking at the output, you can find your server keys if you don’t already know them. The SHA256 hashes in the resulting output are for your server certificates’ public keys.

javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
   Peer certificate chain:
     sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=mobile.myco.com, OU=PositiveSSL
     sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
     sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
     sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
   Pinned certificates for publicobject.com:
     sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
   at okhttp3.CertificatePinner.check(CertificatePinner.java)
   at okhttp3.Connection.upgradeToTls(Connection.java)
   at okhttp3.Connection.connect(Connection.java)
   at okhttp3.Connection.connectAndSetOwner(Connection.java)

iOS

On iOS, certificate pinning can be achieved through a NSURLConnectionDelegate using NSURLConnection. See the OWASP Certificate and Public Key Pinning Technical Guide for more details about this method.

Other third-party libraries that help with certificate pinning on iOS apps include Alamofire and AFNetworking.

AFNetworking offers a simple way of adding certificate pinning to mobile apps. The following snippet can be used to pin one specific certificate of type “cer” from a given bundle. The method below can be called in an init method to ensure that the app rejects all other certs apart from the one pinned.

func certSecPolicy() {
let securityPolicy = AFSecurityPolicy(pinningMode:AFSSLPinningMode.Certificate)
let certPath = NSBundle.mainBundle().pathForResource("pinnedcert", ofType: "cer")!
let certContents = NSData(contentsOfFile: certPath)!
securityPolicy.pinnedCertificates = [certContents];
securityPolicy.validatesCertificateChain = false;
self.securityPolicy = securityPolicy
}

Multiple certificates can also be pinned using the same method. This is useful when the mobile app talks to multiple servers that present different certificates.

Third-Party Libraries

If you’re using a third-party library to handle mobile app network communications, you must update it to to the most recent version. For example, OkHttp versions prior to 2.7.4 and versions 3.x prior to 3.1.2 are vulnerable to MiTM attacks as a result of not sanitizing the server’s certificate chain. The vulnerability has been patched in the newer versions.

Section 5

Testing and Maintenance

The best way (and really the only way) to test mobile app certificate pinning is to execute an MiTM attack against it. For example, if an app relies on a vulnerable version of OkHttp for certificate pinning, mobile app security testing will identify such a vulnerability. If the cert pinning is improperly coded, the test for MiTM will find the gap.

Developers can test this themselves or leverage experienced security analysts. To start, you’ll need a network proxy tool such as Burp Suite, OWASP ZAP, mitmproxy, or Fiddler to intercept mobile app network communications. In order to intercept traffic, you will need to install your chosen proxy tool as a trusted root CA on the test mobile device that will run the app.

Once a proxy is installed as a root CA, it essentially acts as an MiTM and can intercept, decrypt, and modify all HTTPS communications between the device, the mobile app, and backend servers.

If the proxy successfully intercepts traffic while you interact with the mobile app during testing, that’s a sure sign that certificate pinning isn’t enabled. If you believe you’ve properly implemented certificate pinning but the proxy still intercepts your app’s network data, a deeper dive into the app source code may be necessary to determine the problem.

Given the complexity of using OSS tools to test cert pinning, devs without a network security background can turn to security analysts to do the work or use automated mobile app security testing tool. While you may be using static analysis security testing tools (SAST) to automatically scan your source, they don’t test for MiTM attacks — so you will need to add dynamic analysis tools (DAST) to properly test for MiTM attacks.

The most effective way to check your work and ensure the mobile apps you develop are not vulnerable to MiTM attacks is to integrate application security testing (DAST) directly into the DevOps pipeline to security test every build, every day. Automated security testing plug-ins for CI/CD platforms can enable continuous security testing for cert pinning.

Section 6

Countering Objections

Some developers are reluctant to implement cert pinning and may cite a variety of reasons as to why they don’t want to use it in sensitive mobile apps.

They may say using HTTPS for app communications and verifying the CA chain of trust is enough to keep apps secure. But if a malicious root CA is installed on the device and the device is connected to an attacker’s server, the threat actor can still successfully intercept, read, and modify network traffic. Or perhaps they claim that a CA compromise is unlikely, but there are numerous published examples, such as this series of banking apps exposed to MiTM from researchers at the University of Birmingham.

Other developers may attest that implementing cert pinning is too difficult or complicates app builds in staging or QA environments, but it’s easier than you think. There are some simple ways to implement pinning in your app. What’s more, public key pinning can ease the process of migrating code between development environments.

Public key pinning pins the public key of the certificate, which remains constant across multiple certificates. This allows you to use the same public key to issue new certificates without having to rewrite code for different environments.

Some worry that pinning certificates that are bound to change on a regular basis would force them to update the app binary every time the certificate changes. Pinning the hashed public keys of the certificates can also help with this issue. This way, the public key of the certificates must remain static across all new certificates. In addition, backup keys should always be added to the pinning configuration to maintain app connectivity at all times.

Developers may think that their apps don’t transmit sensitive data. But is that really the case and are they absolutely sure? Does your app have login credentials, or account numbers, or PII? Nearly every app does, so nearly every app should take cert pinning seriously. A mistake that leads to data loss could be costly in terms of loss to a company’s data and reputation. Others complain that pinning impedes performance, but benchmarks show that it’s comparable to any form of encryption and secure network transport or they note that their app doesn’t use SSL/TLS. This is an even bigger mistake, as all network communications for any app should be encrypted.

Section 7

Conclusion

As developers seek to build their next great mobile app, there are many security coding best practices to take into account. Proper network security with cert pinning should be very high on that list. While taking the above actions to implement cert pinning may require some extra time to develop, the effort will pay significant dividends. Securing network communications to guard against MiTM exploits protects your mobile app users, your data, and your business reputation.

Implementing cert pinning in your mobile app can strengthen the security of its network communications and is a big step in protecting your app data. Once you invest in cert pinning, test to ensure that you have properly implemented cert pinning to prevent MiTM attacks. While not crucial for every mobile app out there, this measure is critical for any app at that contains high-risk, sensitive data and transactions.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}