Smartphone, tablet, and other hand-held device sales have skyrocketed in recent years. It’s now critical for businesses to provide a mobile option or experience to customers. Additionally, many companies are even created for the sole purpose of making services and entertainment available to their customers’ fingertips—literally.
At the same time, software security initiatives must fall in line with development trends. The Android operating system, by Google, is dominating with over 80% market share for smartphone sales reported in Q1 of 2016. For this reason, today we’ll discuss the best practices for improving the security posture of Android mobile apps.
There are three primary areas that make up the Android OS anatomy:
Every Android application is packaged into a binary (i.e., .apk files—these are essentially zip files containing Dalvik or ART bytecode converted from Java class files at build time) before distribution and/or installation into the Android OS. There are 3 main types of Android applications:
No matter what type of Android application you intend to build, consider the following 10 best practices. Furthermore, when making security decisions, assume that the Android device can be stolen or that an attacker can successfully force the user to run malware on the device.
1. Don’t store unencrypted sensitive data (e.g., PII, credentials, tokens, and cryptographic keys) locally. (This includes the Shared Preferences file system or SQLite database.) Whenever possible, avoid it altogether. Otherwise, use a key derivation function (e.g., PBKDF2) based on user input.
2. Don’t include sensitive data in system logs. Disable debug logging on production builds.
3. Don’t store sensitive data in the WebView cache. In addition to setting up cache control headers in the server-side, the application should clear its cache after receiving sensitive responses.
4. Disable application backup. Backups can potentially allow an attacker to view or modify the application’s locally-stored data without having root access to the device.
5. Protect the readability and integrity of the binaries against reverse engineering-based attacks. There are multiple techniques to ensure this is the case (e.g., code obfuscation and string/class encryption). The table below examines additional techniques.
6. Ensure that the application doesn’t disclose sensitive information through the automatic Android screenshot (i.e., when the application is backgrounded). Rely on the “FLAG_SECURE” attribute or the “android:excludeFromRecents” flag.
7. Determine if the devices your application is running on are rooted. Effective root detection isn’t a simple process and attackers are constantly developing new ways to bypass it. Also establish a risk versus reward determination beforehand. As a starting point, look into the SafetyNet API discussion.
8. Every piece of external communication should occur over a secure channel (e.g., HTTPS).
9. Implement certificate pinning to confirm that the certificate presented by the backend Web service is the one that the application expects.
Applying client-side security controls aren’t enough.
10. Don’t trust your application’s client-side. It’s also important to make security decisions on the server-side when possible.
An actionable lesson to take away is to expand the threat model of any application with a mobile component to consider new threats and attack vectors. This is especially relevant since the attack surface now includes client-side code or application binaries, and the devices themselves.