What is SSL Pinning?
SSL pinning is a technique used in a mobile application to verify that an endpoint the app is calling is using the expected certificate. Its purpose is to detect "man in the middle" attacks where a threat actor simulates your server and inspects the communications between the mobile application and the real server in order to harvest credentials or private information.
The process of SSL pinning involves using a plugin that is used for all HTTPS calls and will check the certificate presented by the endpoint and compare it to the one you have embedded with your application.
The most common plugin used for this is cordova-plugin-advanced-http. There are a few quirks with getting this plugin working with a Capacitor project which are detailed below.
One quirk is that Cordova projects output to the www folder whereas Capacitor ones use the public folder and this plugin (as of v3.3.0) expects certificates in the www folder (a PR to handle this is outstanding).
Why use SSL Pinning?
This technique is a best practice as defined through the OWASP Mobile Application Security guide. The specific guideline is MSTG-NETWORK-3 and if you have your mobile application penetration tested it is likely to be flagged as a vulnerability if your application does not "verifies the X.509 certificate of the remote endpoint".
The technique is a part of a layered approach to security and a defense against a "man in the middle" attack.
Here's the sample project provided for SSL pinning in a Capacitor application:
Certificates need to be stored in the
www/certificatesfolder. One way to ensure this is to create a
srcand then add this to the
- The certificate must have a
- Certificates must be in
Extract certificates via Browser
To extract the DER for a certificate:
- Visit the URL in a browser (Microsoft Edge)
- Click the lock symbol next to the URL
- Click the "Connection is Secure" link
- Click the certificate symbol next to the close button
- Click the details tab
- Click one of the certificates in the hierarchy
- Click Export button
- Choose "DER-encoded binary, single certificate" as the format
- Save the file to your certificates folder with an extension of .cer
- Repeat these steps for each certificate in the chain (that you want to check)
Extracting Certs with Open SSL
This sample app connects to
https://mysafeinfo.com. To extract the public certificates we can call:
openssl s_client -connect mysafeinfo.com:443 -showcerts
- From the output of the command, create a new file in
/certificates(name it .pem)
- Paste into it all certificates shown in the output.
- Certificates start with the line
-----BEGIN CERTIFICATE-----and end with the line
- If multiple are shown, paste them in the order you see them in the output.
- Then convert to DER format
openssl x509 -outform der -in <anything>.pem -out <anything>.cer
Check your Certificate
To validate if your
.cerfile is in the right format (DER) you can run this command:
openssl x509 -in <anything>.cer -inform der -text -nooutIf it throws an error
unable to load certificatethen you know your file is using an incorrect format
- To support Capacitor this PR is needed (you could work around this by putting the certificates in your native projects manually).
- To help with debugging cert issues this PR is needed (which outputs additional information about why a certificate failure occurs).
- A fork with these changes can be installed with
npm install cordova-plugin-advanced-http@https://github.com/dtarnawsky/cordova-plugin-advanced-http
- In iOS 13 additional requirements were added to TLS certificates. These can cause an SSL failure. Read about it here
- Using OpenSSL to extract all certificates in a chain can be a challenge and may not export every certificate. You may need to export from a browser