[SSL Pinning Plugin] SSL Pinning Plugin - Documentation

[SSL Pinning Plugin] SSL Pinning Plugin - Documentation

  
Forge Component
(1)
Published on 17 Aug (4 days ago) by OutSystems R&D
1 vote
Published on 17 Aug (4 days ago) by OutSystems R&D

In mobile apps, SSL Pinning or HTTP Public Key Pinning (HPKP) provides an extra layer of security to HTTPS communications to avoid, for example, man-in-the-middle attacks. It works client-side and adds a verification of the server certificate against hashes of public keys, which are pre-bundled with the mobile app.

How to Implement SSL Pinning in OutSystems

To implement SSL Pinning it is advisable to have two certificates on the server:

  • One to work as the primary certificate; 
  • A second one to work as a backup, in case the primary certificate gets compromised.

The steps to implement SSL Pinning are the following:

  1. Generate hashes for the public keys of the certificates;
  2. Create a configuration file with the hashes;
  3. Add the configuration file to your mobile app;
  4. Validate the certificates against the hashes in the mobile app.

In this document, you’ll also find a section explaining how to test if SSL pinning is working correctly.

Generate the Hashes for Public Keys

To generate the hash for a public key in a certificate, get the certificate from the server and use OpenSSL commands to do the following:

  1. Obtain the public key from the certificate;

  2. Calculate hash of the public key using the SHA-256 algorithm;

  3. Encode the hash of the public key in Base64.

For example, navigate to the server URL and use the browse tools to extract the certificate. Then, use the openSSL commands below to generate the hash of the public key in the certificate:

openssl x509 -in my-certificate.crt -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

For more examples on openSSL commands, check this Mozilla page or this script in GitHub.

Create the Configuration File

Pick the hashes you’ve created and the server address to create a configuration file in JSON with the following format:

{
"hosts": 
   [ {
   "host": "www.myserver.com",
       "hashes": [
           "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
           "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
           ]
   } ]
}

It is important you follow these rules for the configuration file:

  • The JSON structure must be exactly as provided in this documentation;
  • No subdomains are allowed in the host. You must insert the full hostname of your server;
  • Each host should have at least two hash keys: 
    • Each hash must be prefixed by sha256/;
    • No duplicate hash keys are allowed with iOS;
    • If using the OutSystems personal environment, there’s only one certificate (and hash key). Use a dummy text for the second hash key.
  • The file must have a .json extension, e.g., pinning.json.

Add the Configuration File

With the configuration file in hand, add it to the mobile app to be bundled with it.

In Service Studio, do the following in the mobile app: 

  1. Add a Resource to the module with the configuration file;
  2. Set the Deploy Action property to ‘Deploy to Target Directory’;
  3. Set the Target Directory property to ‘pinning’ (without quotes).

It must exist only one JSON configuration file as Resource or, otherwise, SSL Pinning may not work as expected.

Implement the Extra Verification of a Server Certificate

To add the SSL Pinning verification, first get the SSL Pinning component from the Forge and install it in your environment.

In Service Studio, do the following in the mobile app:

  1. Go to Manage Dependencies and add the reference to SSLPinningPlugin;
  2. Drag the RequireSSLPinning block to one of your screens (suggestion: the Splash screen), and SSL Pinning will work for all HTTPS requests in the mobile app.

Test SSL Pinning

To test the mobile app with SSL Pinning, do the following:

  1. Publish and generate the new version of your mobile app with SSL Pinning; 
  2. Install it on your smartphone and run. 

Since you have the right certificate and hash keys, the mobile app should work as before.

To see SSL Pinning in action, i.e., rejecting a certificate, do the following:

  1. Edit the configuration file and tamper the hashes (for example, change one character in each hash);
  2. In your mobile app:                
    1. Remove the resource with the old configuration file;
    2. Add a Resource with the new configuration file (don’t forget to set the properties);
    3. Publish and generate the new version;
  3. Install the new version on your smartphone and run.

At this point, the mobile app won’t work because SSL Pinning will raise an error due to an invalid certificate.

SSL Pinning for Multiple Servers

If you want your mobile app to perform SSL pinning validations while connecting to multiple servers, proceed as follows:

  1. For each server, get its two certificates and generate their hashes;
  2. Create the configuration file in the following JSON format:
{
    "hosts": [{
       "host": "www.myserver1.com",
       "hashes": [
           "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
           "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB="
           ]
   },{
       "host": "www.myserver2.com",
       "hashes": [
          "sha256/CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=",
          "sha256/DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD="
          ]
    },
    ...
    ]
}
  1. Bundle the configuration file and implement the verification in your mobile app as explained for a single server.


Limitations

  • Blob URLs currently are not supported for SSL Pinning implementation on Android. 

What does this mean?

This mean, when made an XHR request with a Blob URL, SSL Pinning implementation will abort this request because, for now, doesn't have support to deal with it. 

Hello Jaime,


Is It possible to generate and use an hash from the root certificate (or intermediate certificate) since it has more extended expiration date?


Appreciate your help.


Cheers,

Ricardo Brito

Hi,

This site generate the hash:

https://report-uri.com/home/pkp_hash

Cheers,

Bruno Cantante

Hello!

I'm starting to be upset by not having an error at all :(

I'm using it on my personal environment to test this and it doesn't matter the hash I use in the configuration file, it always works!

Can anyone confirm that the plugin is working the way it should?

Thanks!

Hello, Mikael,

Have you re-generated and reinstalled the app after updating the hashes? Remember that, for these native changes such as these to become effective, a new app must be generated.

Best regards,

Carlos Simões

Carlos Simões wrote:

Hello, Mikael,

Have you re-generated and reinstalled the app after updating the hashes? Remember that, for these native changes such as these to become effective, a new app must be generated.

Best regards,

Carlos Simões

Hi Carlos,

Yes I've done that several times and nothing changed


I see. The other thing that happened to me a couple of times was that I mistakenly thought connections were being allowed, while in reality the app was still working, but in offline mode (AFAIK, this is only the case for one of the platforms, Android I think).

Could you please sanity check if calling a server action on the app is successful?

Best regards,

Carlos Simões

Carlos Simões wrote:

I see. The other thing that happened to me a couple of times was that I mistakenly thought connections were being allowed, while in reality the app was still working, but in offline mode (AFAIK, this is only the case for one of the platforms, Android I think).

Could you please sanity check if calling a server action on the app is successful?

Best regards,

Carlos Simões

I'm able to login and logout successfully. I will try to make other kind of test/ debug but i think this is a good example of server action being called.

If you haven't changed any of the default Login logic, then yes: a server action is definitely being called.

Well, it looks like you've checked pretty much everything. As a final sanity check, could you confirm if the "pinning.json" file points to the exact hostname you are trying to pin? Wildcards and sub domains are not allowed, so it must match the hostname you want to validate exactly.

If that checks out, could you please open a support case with us, so we can have a look at what's wrong?

Thank you for your patience, and best regards,

Carlos Simões