I am going to start this blog with a fact. Security has become increasingly important in the software development sector, let alone in Android app development.
Keeping the personal and business information on Android devices safe has become a concern for many. As the number of Android users is increasing day by day, organizations and individuals developing android apps need to be proactive and take steps towards keeping information safe.
In this blog, we will talk about the security best practices for Android apps and how IT organizations can take the necessary steps for the same.
What are Android security best practices?
As the name suggests, the Android Security best practices are actions taken to secure Android apps and avoid unwanted access of data within and outside the app. For example, Android apps can be accessed from a network (WiFi, Bluetooth) which is commonly neglected.
If you want to know more about the vulnerabilities present in Android, you can check it out here.
However, there are a few common mistakes novice developers make and can be avoided, which are:
- Writing logs (for example log.d (TAG, password)) for sensitive data which will be shown in logcat. Here, sensitive information indicates credit card number, username, email, password, ID cards and more.
- Copying code from the internet without being aware of what it is and the impact it will have on the app security. For example, Android apps are built of different types and flavors into production, development, QA etc. Majority of the time, only the production server is SSL compliant; whereas the development and QA servers are not.
For that reason, during the QA/development stages, the app will not allow calling HTTP (non-SSL) requests. In order to solve this, you visit stackoverflow and you find this solution,
<application android:usesCleartextTraffic="true" ...> </application>
Even though this code will work for HTTP and HTTPS requests, it will also allow the production app to call any HTTP request which is serious if you are allowing third party http requests.
- Content providers offer data storage access that can be either limited to your own application or exported to be accessible by other applications. If you do not intend to provide other applications with access to your Content provider, mark them as android:exported=false in the application manifest. Otherwise, set the android:exported attribute to true to allow other apps to access the stored data.
What are the security best practices for Android apps?
While you might be already following some basic security practices, I am sharing a few more with proper categorization to help you decide faster on a plan of action.
The Android security best practices are divided into three aspects:
- Network security
- Data security
- Code security
Let’s explore them one by one.
Network Security Best Practices for Android Apps
Here is how to ensure the ultimate network security for Android apps.
Re-check network security configuration
If your Android app communicates with a web server that has a SSL certificate issued by a well-known, trusted CA, it is recommended to use below code in your App’s manifest XML.
<application android:networkSecurityConfig="@xml/network_security_config" ... > </application>
Add an XML resource file for each build type(prod, dev, QA), located at res/xml/network_security_config.xml.
Create different files for prod and QA/dev and specify that all traffic to particular domains should use HTTPS by disabling clear-text or HTTP by enabling clear-text.
So your prod network_security_config.xml will look like
<network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> ... </domain-config> </network-security-config> And QA/Dev file will look like <network-security-config> <domain-config cleartextTrafficPermitted="true"> ... </domain-config> </network-security-config>
An SSLHandshakeException can occur in case of several scenarios, such as:
- The CA that issued the server certificate was unknown
- The server certificate wasn’t signed by a CA, but was self signed
- The server configuration is missing an intermediate CA
Make WebView Safe
A WebView displays web content using HTML and JavaScript. An improper use of Javascript makes way for common web security issues such as cross-site-scripting. There are 2 scenarios to use WebViews in Apps:
- Show HTML content
- Get call backs from HTML-Javascript to Java/Kotlin. Or send data objects from Java/Kotlin to HTML-Javascript.
However, there are a few things you need to consider before using WebView:
- If the app doesn’t use JavaScript for WebView directly, then don’t use setJavaScriptEnabled(). It can lead to cross-site-scripting.
- If your app needs Javascript, try using the below mentioned options:
- loadUrl(“javascript:…”), evaluateJavascript(), this is the first choice of the app developers that invokes JavaScript code from the Java native layer. These methods use strings to invoke and expose objects. Using a hardcoded string does not incur much threat. However, using a dynamically created string can invoke unwanted scripts for which you have no way to control.
- Use addJavaScriptInterface() allows JavaScript to invoke operations that are normally reserved for Android applications. You can add a Java object using addJavaScriptInterface(), which will be accessed by Javascript and allow it to invoke Java methods. However, addJavaScriptInterface() has bugs, so make sure to use it with care. An alternative to addJavaScriptInterface() is HTML Message Channel discussed in the following point.
- Because the addJavaScriptInterface() has security bugs, the HTML Message Channel is an alternative solution provided by Google. Google says “Use HTML message channels instead of communicating between a website and your app, as shown in the following code snippet.”
val myWebView: WebView = findViewById(R.id.webview) // channel[0] and channel[1] represent the two ports. // They are already entangled with each other and have been started. val channel: Array<out WebMessagePort> = myWebView.createWebMessageChannel() // Create handler for channel[0] to receive messages. channel[0].setWebMessageCallback(object : WebMessagePort.WebMessageCallback() { override fun onMessage(port: WebMessagePort, message: WebMessage) { Log.d(TAG, "On port $port, received this message: $message") } }) // Send a message from channel[1] to channel[0]. channel[1].postMessage(WebMessage("My secure message"))
Give a Try to Authentication
If you have multiple apps or even if you have a single app and don’t want to expose passwords then you can use AccountManager. The account manager lets you get authentication tokens for different services.
Data Security Best Practices for Android Apps
Now that we have covered the best practices for network security, let’s understand the same for data security.
Database Management
Now, Android developers use the SQLite database. The database is stored in the file system and therefore, not accessible to other apps. But their threat can be recovered if the device is not encrypted. Android provides a room that poses as a great wrapper around SQLite providing you protection against such threats.
Furthermore, third-party databases like Realm can also be put to use as they claim thorough encryption.
File Storage
The most common concern and security threat for Android apps is that stored files can be accessed by other apps as well. However, Google is working on a few updates to avoid such external accesses. For example, to access media and shared files, you have to use the Media Store API.
In addition, Android 11 introduced Scoped storage enforcement, which allows apps to store and access files in a dedicated location so that apps can not access these files. However, the versions previous to Android 11 can access those files. You can use encryption and EncryptedFile objects available in the Security library to solve this problem and restrict access to files from other applications.
SharedPreferences
This is a common mistake that developers make while considering security aspects of Android apps. You should always MODE_PRIVATE to access your app’s SharedPreferences objects. But if you want to share data across apps, don’t use SharedPreferences objects. Instead, you should follow the necessary steps to share data securely across apps.
Best Code Security Practices for Android Apps
Let’s cover the best code security practices now.
Avoid reverse-engineering
Now, the Android apps can be reverse engineered using relevant tools; which is difficult to prevent.
- You should use the Proguard tool, which is an open source command-line tool that shrinks, optimizes and obfuscates Java code. This is a known Java technique. DexGuard is a commercial version of Proguard, which decompiles the code, thus making it hard to read for the attacker.
- To avoid reverse engineering, some experts recommend using C/C++ code in Android apps for critical functionality. If you develop a critical functionality in NDK, it will produce a .so file; which can be further decompiled; eventually requiring the attackers to have knowledge of processors and assembly languages.
Load the code dynamically
Google strongly discourages executing code from outside of the app. Such as, loading code from the server and executing it in apps. This practice increases the threat of code injection or code tampering.
In Conclusion
If you think about it, you’ll find an infinite number of tips, tricks and practices to follow to secure Android apps. But the ones which work effectively and practically, are the best ones.
In this blog, I have done my best to share the security best practices that you can put to use right away for your Android apps. I hope these help you.