Mobile App Security: A Deep Dive into
12 MIN READ /
Secure Software Analyst | code4thought
Secure Software Analyst | code4thought
In the ever-evolving digital landscape where mobile phones become more and more integral to our daily lives and where their traffic accounts to 59% of the total web traffic worldwide, the need to ensure the security of mobile applications and their users has never been more crucial.
In this article, we are going to talk about defensive measures that can help developers and organizations build resilient and secure mobile applications. Then, we are going to outline how to manage user credentials in mobile applications in a secure manner in the most popular mobile development platforms.
Strategies and Techniques to build resilient mobile applications
When it comes to mobile applications, they are downloaded by a user on their device in the form of a compiled binary package which contains the applications source code in a compiled or binary format. This sets the stage for a malicious actor to try to analyze and reverse engineer the compiled application in order to extract the underlying source code of the application. From the extraction a malicious actor can benefit from the below:
- Identification of weaknesses within the application such as endpoints that might not require authentication because of a design mistake.
- Extraction of secrets, hardcoded accounts or other sensitive information that might be embedded within the application’s source code(if you want to learn more about why hardcoded credentials pose a significant risk check out our previous article on the topic which can be found here).
In order to increase the effort needed to understand or reverse engineer the application and to discourage casual reverse engineering attempts, we need to implement certain measures. Before we start, it needs to be mentioned that no defense measures can provide 100% protection against reverse engineering.
The measures that someone can implement can be found below:
When we are talking about obfuscating the code in mobile applications we are referring to the process of changing the code in order for it to be less recognizable to the malicious actor. Thereby making the reverse engineering process more costly. This is achieved through the use of the following techniques:
- Insertion of decoy logic & nonsense statements
- Encryption of segments of the binary code
- Obfuscation of the control flow of the application
This implementation aims to prevent malicious actors from jailbreaking (IOS) or rooting (Android) devices, meaning gaining administrator level access on their mobile device in order to bypass restrictions made by the OS creator. By bypassing those restrictions the actors have more control over the device making it customizable by giving the ability to access system files, settings and having higher privileges (administrator privileges).
In order to understand better how this higher access could be used, let’s take an example where a malicious actor would trick an application that he is in a different location than he actually is thereby bypassing certain application restrictions and security features. Such an example can be found in the case where Niantics (the company who developed the mobile game Pokemon GO) struggled with users who were spoofing their location (meaning faking their real location through use of software that was deemed unauthorized by the OS creators) in order to be able to cheat in the popular mobile game Pokemon GO.
This gave an advantage to the users resulting in situations which could lead to economic gain(by selling accounts with a lot of progress in the game etc.). Thereby hindering the integrity of the mobile game.
- Checksum validation: This refers to the case where a mobile application uses a hashing algorithm to calculate the checksum of its executable code and stores its result in server-side storage or within the application with additional security hardening measures such as whitebox cryptography (combining encryption and obfuscation in order to embed values within the application).
- Emulator/Debugger detection: This refers to the case where the creator of the mobile applications has written source code with the aim to detect if the application is running on a debugger or if there are specific debugging techniques used (breakpoints or memory dumps). Thereby creating a mechanism where if such detection occurs it would instruct the application to crash.
With binary protections in mobile applications we refer to mechanisms that are implemented in order to make it more difficult for malicious actors to tamper and exploit the applications executable code. Some notable mechanisms include the following:
- Stack Canaries
- Address Space Layout Randomization (ASLR)
- Data Execution Prevention (DEP)
- Control Flow Integrity (CFI)
These mechanisms aim in the most part to make the operations of the application unpredictable and such that they can not be tampered. They try to reach that result by randomizing memory addresses used, predefining call targets meaning how the control flow of the application will go and tampering detection techniques.
Securing user credentials in mobile applications
Now that we have discussed how to make our application more resilient, in order to ensure its overall safety, we also need to talk about how to securely manage user credentials. Before we dive into the process we need to first understand why we need to securely manage credentials and also what types of credentials we are going to be managing, in order to follow the best approach.
We secure user credentials in encrypted storage in order to prevent the following situations:
- Leakage of credentials from malicious applications within the same device
- Extraction of credentials from unencrypted memory from malicious actors in case of the device being stolen or tampered
Types of credentials found in mobile applications
Credentials that are found & saved in mobile applications can be categorized in the following:
- User credentials
- Login credentials (username/email & passwords)
- Login PIN (Quick pin in order to login into applications)
- User access tokens
- Application credentials
- Authentication tokens in order to connect to external services
- Hardcoded accounts in order to connect to external services
- User access tokens
- Encryption keys
- Hardcoded IVs
- Hardcoded salts
- Hardcoded Credentials (User or Admin)
- API Keys that are needed in order to perform intended functionality
Now that we know the types of credentials we are going to manage, let's talk about the process of securely managing them in the platforms iOS & Android.
Securing credentials in Android applications
Android provides a system named Android Keystore in order for applications to store generated encryption keys in a secure way, by protecting the values from unauthorized use. Android Keystore secures them in 2 ways:
- Values that are stored in the Keystore never enter the application process and also when an application needs to use a certain key in order to perform cryptographic operations on application supplied values, the operations are fed to a system process that performs the cryptographic operations.
- “It gives the ability for applications to store their key material in secure hardware within the Android device such as the Trusted Execution Environment (TEE) or Secure Element (SE)”.
Android Keystore functions:
- Generation of random keys
- Secure storage of keys
Let's imagine a scenario where a mobile application has a sensitive value that needs to be embedded within the application (saved in Android Preferences). In order to secure it, it will perform the following:
- Request a random key from Android Keystore
- Store the generated key in the Keystore
- Use it in combination with strong cryptographic algorithm such as AES in order to encrypt the sensitive value
- Save the encrypted value in Android Preferences
Securing credentials in IOS applications
Like Android, IOS also provides a system in order for applications to store sensitive information. In the IOS case, the system is named Keychain Services API which basically provides a container or in other words a database that is stored in the device which performs encryption automatically (Keychain Services API is also available in Mac OS). When the Keychain is locked it is impossible to access or decrypt the values within the keychain.
The Keychain Services API has a different use case than the Android Keystore. It differentiates through the ability it gives to the applications not only to store encryption keys but also sensitive values such as login credentials, quick PINs, etc. So, instead of using a generated key in order to encrypt a value in the application, with IOS Keychain the application directly stores the sensitive values in the Keychain.
Securing credentials in Cross Platform applications
In the case of Cross Platform Applications such as mobile applications that were developed with react native, there are libraries created by the community that perform the management of credentials on their own by using the techniques discussed above in the respective platforms. Resulting in the situation where the developer only needs to configure the library and use the functions that the library provides in order to store and retrieve the sensitive value it wants to manage. One example of such a library that implements the techniques and provides the above functionality, is react-native-keychain.
In conclusion, implementing resilience measures and securely managing user credentials are a must have feature for today's mobile applications in order for users to trust the application and to prevent exploitation of potential undetected vulnerabilities. But, as mentioned above there are a lot of options that someone can implement when developing a mobile application in order to make their applications more resilient. Leading to the situation where the more defense layers an application has implemented, the better. In an ideal situation a mobile application would implement a combination of all the above in order to get the best result possible.