Network data channel protection for Android applications

Network data channel protection for Android applications

Apr 10, 2019

User information protection is a great issue today, especially with GDPR being actual for over a year already. Most of the mobile apps have a login option and most of them have a local database that stores sensitive information.

One of the applications that our company was involved in developing was hacked by reverse engineering and repackaging. It was an application with over 50 million downloads and 1.5 million monthly active users at the moment we received a project. Since this project was under our developmental control, we had to think fast. It is worth noting that this application was already using Proguard obfuscator, the network communication was already wrapped with SSL, and the local database was encrypted. Nevertheless, an attacker was able to repackage the application and connect to our API. We resolved the issue using a complex approach by protecting our API and using advanced code obfuscation techniques.

However, this article is not about the steps we made in this particular case. I would like to highlight security issues that should be considered while developing the mobile application.

When the application has a login form, in most cases that means that the username/email and password will be transferred to the backend for user authentication. There is a common practice as to how to normally send this information to keep it safe.

Recommendation 1. All the network communication should be done using HTTPS protocol.

Of course, the HTTPS communication channel can be compromised using different techniques including the most commonly used one: the man in the middle attack. It’s a situation when the attacker can intercept messages from the private channel, substitute HTTPS certificates and can then listen to the private channel messages and even change them since he owns the substituted certificate. This can be avoided by using a mechanism to protect the HTTPS channel from the man in the middle attack.

Recommendation 2. Use SSL pinning to protect HTTPS channel from MITM attacks.

SLL pinning is a client verification of the SSL certificate that is used on the backend to undersign HTTPS packets. This means that the backend SSL certificate should be incorporated into the client application so that the client can validate the HTTPS packets signature.

SSL pinning brings a high security level in the communication channel and at the same time it also brings additional difficulties in application support. The key point is that SSL certificates have a limited lifetime and they should be updated when the previous one expires. Since the backend certificate changes, it should also be refreshed on the client side for the proper validation. It’s not a problem for the developer to update the certificate and release a new application version to the Google Play, but not all users have automatic application updates enabled in their settings and some of them may not have a proper network channel where they can perform an update. Therefore, you can either block the application until the user updates it or you have to think how to update the certificate without updating the application. There is another problem here: since your certificate has expired, you don’t have a completely secure channel to safely transfer certificates. To solve such a problem, there are a couple of available options that I have experienced in my practice.

Option 1. Have a separate backend to store actual certificates. Communication to this backend should be protected with SSL pinning with only one key difference: the SSL certificate for this backend should have an extra lifetime. In this case, you will be able to fetch securely the updated certificate for the communication to the main API backend and to update the certificate to the certificate storage once you update the application on Google Play. Of course, it is always best to block an application when the SSL cert in the certificate storage is outdated.

Option 2. Encode a new certificate on the backend with a secret key and send it to the client side to decode it. There is one huge drawback with this approach: the secret key should be locally stored in the application. The key can be easily fetched using a reverse engineering technique if it’s not hidden. Of course, there are techniques to obfuscate the key in the application. However, that’s another topic and it will be covered in another article.

One thing I have to mention here is that it really depends upon which certificate the validation is going to be made. On the top of the certificate chain, there is an absolute trusted certificate authority (CA) that is an issuer for all other certificates. CA can issue regular certificates as long as other CA’s can also issue final certificates. Information about the chain is stored in the issued certificate. Developers can perform SSL pinning on the actual certificate that is used by the backend as long as it can be performed against the CA that issued this certificate. When you do SSL pinning against the lower certificate (the one that is used on the server), it provides you the highest protection since it’s the last node in the chain and it cannot be compromised. You can also do SSL pinning against CA at any level since it has a longer lifetime than your final certificate. However, you have to understand that two different certificates can be issued by this particular CA. If an attacker substitutes such a certificate using an MITM attack, then the channel will be compromised.

SSL pinning is really easy to implement using Retrofit library. Here is an example of how you can create HttpClient with SSL pinning.

Builder builder = new Builder();
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.writeTimeout(30, TimeUnit.SECONDS);
builder.certificatePinner(new CertificatePinner.Builder()
                    .add("api.example.com", “sha256/{cert_hash}”)
OkHttpClient okHttpClient = builder.build();

And here is how you can get SSL certificate digest

openssl x509 -in "/path_to_folder_containing_cert/backend_cert.pem" -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64 

It can easily be converted to Java code using a java security.* package


As you can see, it’s really easy to provide a protected communication channel on the mobile application. We have covered only communication channel security here, but we will also talk about secure local data storage in the next article.

Using Corsac Blog and website you agree to our Privacy Policy and Terms and Conditions.