During numerous mobile app security assessments we faced fintech apps for Android, that had an option to protect user data with biometric authentication, but failed to implement it in a secure way leading to authentication bypass. Although the security risk is very low due to attack-specific prerequisites, such as acquiring physical access to a mobile device and escalating privileges to root, but generally it is required and expected that banking and fintech apps will provide the highest level of security.
Let’s take the Revolut Business mobile app as an example. It generates a master encryption key and stores the generated key in the Android Keystore system, which prevents key extraction. When a user enables biometric authentication in the Revolut Business mobile app no new encryption key is generated and bound to biometric authentication. Instead, the same master key is used to encrypt a shared preferences file, which stores a user’s passcode when biometric authentication is enabled. This can be exploited using a dynamic binary instrumentation framework, such as Frida, when the attack-specific prerequisites are met. The framework is used to hook or call arbitrary methods within an application completely altering its execution flow.
The following video demonstrates that it is possible to force the Revolut Business mobile app to decrypt the contents of the shared preferences file and retrieve the passcode, which is used to authenticate to the mobile app – bypassing biometric authentication. Therefore, an attacker who has physical access to a mobile device and is able to obtain root privileges on it, will be able to access Revolut Business account due to imperfect implementation of biometric protection.
The following are general guidelines on how to correctly protect sensitive data with biometric authentication:
setInvalidatedByBiometricEnrollment:True setUnlockedDeviceRequired: True setUserAuthenticationRequired: True setUserAuthenticationValidityDurationSeconds: -1
Start a biometric authentication workflow that incorporates a cipher object that is initialized from the key, which is bound to biometric authentication (setUserAuthenticationRequired: True).
Within your biometric authentication callbacks, use the secret key to decrypt/encrypt the sensitive information.
More information can be found at: https://developer.android.com/training/sign-in/biometric-auth
This issue was reported to Revolut through a Bugcrowd program and was marked as “Not applicable”, therefore this example is made public for the benefit of app developers as maintaining a healthy level of security hygiene in a financial app is a sign of commitment to your customers.