3.3 Fully Validate SSL/TLS
An application not properly validating its connection to the server is susceptible to a man-in-the-middle attack by a privileged network attacker. This means that an attacker would be able to capture, view, and modify traffic sent and received between the application and the server.
Developers may disable certificate validation in apps for a variety of reasons. One example is when a developer needs to test code on the production server, but does not have a domain certificate for the test environment. In this situation, the developer may add code to the networking library to accept all certificates as valid. Accepting all certificates as valid, however, allows an attacker to execute an MITM attack on the app by simply using a self-signed certificate. This approach to developing an app nullifies the effect of SSL/TLS and provides no value over an unencrypted, plaintext connection (other than requiring an active MITM attack to view and modify traffic whereas a plaintext connection can be monitored passively).
Below is an example of vulnerable Android code that accepts all SSL/TLS certificates as valid:
Another common developer mistake in the implementation of SSL/TLS is setting a permissive hostname verifier. In this case, the app won’t accept self-signed certificates because the certificate is still validated. But if an app “allows all hostnames,” a certificate issued by any valid certificate authority (CA) for any domain name can be used to execute an MITM attack and sign traffic.
Below is an example of vulnerable Android code that sets a permissive hostname verifier:
- Hostname validation: The app must check and verify that the hostname (Common Name or CN) extracted from the certificate matches that of the host with which the app intends to communicate.
Android 7.0 (API level 24) has introduced features that affect certificate pinning and validation. Android 7.0 will only trust a preselected list of certificate authorities (CAs) maintained by the Android Open Source Project and will not trust custom CAs or CAs added by a user.
Developers can, however, direct Android 7.0 to maintain trust with a custom CA throughout the entire app or specific domains using the Network Security Configuration file. Developers can also use the Network Security Configuration file for certificate pinning (see Android documentation about the Network Security Configuration feature.
Pinning certificates to a default Apache HTTP client shipped with Android consists of obtaining a certificate for the desired host, transforming the cert in .bks format, then pinning the cert to an instance of . BKS keystores are usually included within the assets/raw directory of the app’s APK file.
The following sample code demonstrates how a BKS keystore can be loaded:
` InputStream in = resources.openRawResource(certificateRawResource);
The following sample code illustrates this approach:
` HttpParams httpParams = new BasicHttpParams();
For more information on implementing certificate pinning in Android, refer to the OWASP - https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#Android.
In addition, is a library that backports the Android 7.0 network security configuration subsystem going back to API level 17 (Android 4.2), which makes it easier to tie an app to particular certificate authorities or certificates, support self-signed certificates, and handle other advanced SSL certificate scenarios.
One option is to use or classes to achieve certificate pinning in iOS. Additional details on this implementation can be found in the technical note “HTTPS Server Trust Evaluation” at .
In addition, TrustKit, an open-source framework, can help make it easier for developers to deploy public key-pinning in iOS.