Network Security for Android Developers (MitM attack & SSL Pinning)

Joshua Park
4 min readJan 4, 2021

This is a summary of what I have been learning about Network Security from an Android developer perspective. How to enhance your mobile security.

Why is SSL/TLS required? What is a man-in-the-middle(MitM) attack?

Without the SSL/TLS end-to-end encryption, a hacker can:

  • See your user name, password when you login
  • See your auth token for any API calls you make to the server
  • Alter information so that you could send money to the wrong account (see above image)

SSL vs TLS

SSL was replaced by TLS. TLS is the superior version of SSL. Although SSL should no longer be used, the name is still widely being used.

SSL version updates

The SSL version has been updated from SSL 1.0, 2.0, 3.0 to TLS 1.0, 1.1, 1.2, 1.3. The security vulnerabilities continuously have been found and updates have been made.
GlobalSign warns to disable TLS 1.0 and below. There are more and more enforcements for payment services to use at least TLS 1.2. Stripe, for example, blocked below TLS1.2 as of June 13, 2018.

Headache of supporting minimum TLS version

So what’s the issue? Just use the highest TLS version. There’s an issue for older devices.

TLS 1.2 was supported on devices with android API levels on 16+(4.1) but was only enabled by default on devices on level 20+ (5.0).

For devices below Android 5.0, it is up to each Manufacturer to include TLS 1.2 support or not.

If you upgrade the server to support TLS 1.2+, then you will encounter the TLS version not supported issue for Android 4.x devices. You can simply make the minimum Android SDK version to 5.0. However, if you still want to support Android 4.x devices, some users will be able to download from the Play Store only to find out their device is not supported (due to the manufacturer not including TLS 1.2 support). This will result in bad Play Store ratings.

There is a way to programmatically detect if the TLS version is supported or not. You should throw some type of appropriate minimum security requirement error message.

This headache will happen once again in the near future when the TLS 1.3 becomes the minimum requirement.

Minimum TLS versions

Refer following for TLS version support per Android version:

https://developer.android.com/reference/javax/net/ssl/SSLEngine
This website also contains the Cipher suites availability per Android version.

What happens during a TLS handshake?

Detail Source

During the handshake, the server verifies the client and the client verifies the server. How does the client know the server is who they say they are? If you’re buying a house, how do you know if the seller is the true owner of the house? You have to ask some sort of trusted authority (government) to verify the house is truly owned by this seller. This “trusted authority” is the Certificate Authority(CA) for networks. What if the seller brings the fake government verification paper to you and you have no idea if it is a fake or not? Likewise, if the wrong root certificates are added on the device, then this “fake” certificate will be trusted.

Charles

Charles is widely used for the debugging and analyzing. Charles can see the unencrypted contents by installing it’s own root certificate and making the device (or browser) trust the certificate.

SSL Pinning comes to rescue

By providing the “true” server public key information, you can restrict the application to only trust the provided public keys for certain domain names.

For example, if the domain name starts with *.example.com, trust it only if the public key is SHA256/AAA. Hackers cannot* create a certificate with the same public key.

How to get the server’s SHA256 public key?

  1. Use https://github.com/scottyab/ssl-pin-generator to get the SSL pins.

2. Use https://www.ssllabs.com/ssltest/analyze.html

How to enable SSL Pinning?

Enabling SSL Pinning using OkHttp is following:

val certificatePinner = CertificatePinner.Builder()
.add(
"www.example.com",
"sha256/ZC3lTYTDBJQVf1P2V7+fibTqbIsWNR/X7CWNVW+CEEA="
).build()
val okHttpClient = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()

Examples for other popular network libraries are here.

For Android 7.0+

For Android 7.0+, you can add it to the networkSecurityConfig config file.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">example.com</domain>
<pin-set>
<pin digest="SHA-256">ZC3lTYTDBJQVf1P2V7+fibTqbIsWNR/X7CWNVW+CEEA=</pin>
<pin digest="SHA-256">GUAL5bejH7czkXcAeJ0vCiRxwMnVBsDlBMBsFtfLF8A=</pin>
</pin-set>
</domain-config>
</network-security-config>

See following for the details.

What is the expected result?

When the hacker tries the man-in-the-middle(MitM) attack, the application will result in SSL Pinning mismatch and throw an exception.

Certificate Expiry

Certificate expires. We don’t want older app versions to stop working because the server certificate is renewed. So you might want to avoid hardcoding the SSL pin inside the application code. Make it so that it dynamically downloads the SSL pin from the server.

--

--