bitwarden / mobile

Retired Bitwarden mobile app for iOS and Android (MAUI/Xamarin).
https://bitwarden.com
GNU General Public License v3.0
103 stars 12 forks source link

[Android] Forcing user to re-authenticate if the system fingerprint settings are changed #666

Open FW1F0lgOEI1slIdoXx5P5pGUCOf7Ej6OBNLSsbk opened 4 years ago

FW1F0lgOEI1slIdoXx5P5pGUCOf7Ej6OBNLSsbk commented 4 years ago

This is strictly related to Android. While playing around I noticed that removing a fingerprint from my device and adding a new one does not affect Bitwarden's fingerprint unlock at all. Simple way to reproduce this would be:

  1. Enable fingerprint locking with Fingerprint A
  2. Remove Fingerprint A through Android's system settings
  3. Register Fingerprint B in Android's system settings
  4. Successfully unlock Bitwarden with Fingerprint B.

As a counter-example to this, a mobile banking application that I use (with fingerprint unlocking support) forced me to re-authenticate with a password after I followed the steps described above.

While this whole thing is technically only a risk when someone has physical access to the device, I can see a scenario where a user's carelessness can lead to issues.

Question is, should the user be forced to re-authenticate when device fingerprints are changed? It seems that this is technically possible. Any thoughts on this?

pPmnBRRYhIemiuiy3VBYULJIzQyZaEvWMbCPH1P commented 4 years ago

This is expected today. I could possibly change it to disable the fingerprint option Bitwarden if it detects the device's fingerprint settings have changed. The only issue there is I don't know how to detect that event. Do you?

FW1F0lgOEI1slIdoXx5P5pGUCOf7Ej6OBNLSsbk commented 4 years ago

Some quick googling suggests that Android's KeyStore API can be set up to invalidate fingerprint-associated keys when new fingerprints are added to the device. Alternatively, the FingerprintManager API may be used somehow.

I'm not exactly sure how fingerprint locking is implemented in Bitwarden so I'll try and set up a dev environment and play around with the code a bit. I'll let you know if I find a solution.

FW1F0lgOEI1slIdoXx5P5pGUCOf7Ej6OBNLSsbk commented 4 years ago

Okay so I looked into this and here's what I found. As of right now the application makes no specific distinction between a fingerprint lock and other locking options (let's say PIN).

When unlocking the vault, the application simply asks the OS to authenticate the user using the native biometrics prompt. Upon successful authentication, Bitwarden simply flags the fingerprint lock as "unlocked" and proceeds to retrieve the vault key (master password or encryption key, I'm not sure which one) from secure storage.

I looked into the source code of Xamarin's secure storage and it seems they are using Android's KeyStore API to generate keys which are then used to encrypt the stored values. The encrypted values are then stored using SharedPreferences.

Note that the KeyStore API has a way to generate keys which require user authentication in order to be used and make those keys become invalid when fingerprints are added/removed. Xamarin's Secure Storage however, does not use this option, meaning that those keys are always retrievable (within the context of the app) despite changes to device's security settings.

A proposed solution to this would be to re-write the biometric authentication implementation for Android. This would mean generating a new key using the KeyStore API whenever a user enables fingerprint locking and using that key to encrypt the vault key (and manually storing the encrypted vault key somewhere). This way, if we try to use the key after adding/removing fingerprints, the KeyStore will throw a KeyPermanentlyInvalidException which we can handle by requesting the user to re-enter their master password and forcing them to manually re-enable fingerprint locking via Settings.

Any thoughts on this? The proposed solution would require a lot of work. Feel free to correct me if I've made any mistakes with the way fingerprints are currently handled.

PdTfdht8d5D5RgVFqlOFoKRizB95kmhJwDlV28V commented 4 years ago

Hi, I'm no expert, but reading this Stackoverflow article , it seems simple enough. From the article: So to check if any new fingerprints have been enrolled since you created your fingerprint-associated key, just create a cipher with that key and try to init the cipher. If any new fingerprints have been enrolled, the init call should trigger a KeyPermanentlyInvalidatedException Could this work?

FW1F0lgOEI1slIdoXx5P5pGUCOf7Ej6OBNLSsbk commented 4 years ago

@smanelli That solution seems roughly the same as the one I described earlier, and it makes sense to use Android's built-in API to invalidate keys when biometric options change.

If I recall correctly, right now the vault key is stored using Xamarin's "secure storage". The problem is that Xamarin is also the module which is responsible for getting the keys which are used to encrypt items in secure storage. While its handy and all, this means that we can't directly use Android's key invalidation API.

SQgiLVA2bwPKqnODbOEtOdbcRbTNjr3vZobWRCC commented 8 months ago

Hello there, was there any progress since?