What are the benefits to using Jetpack's EncryptedSharedPreferences and EncryptedFile?
Asked Answered
S

2

8

After reading over tons of articles and stackoverflow posts, I can't find a concrete reason to use EncryptedSharedPreferences or EncryptedFile compared to using their non-encrypted counter-parts.

To start off with, I want to talk about the 2 states of a device that security must be thought about:

  • the device is not compromised
  • the device is compromised

When the device is not compromised, the application is sandboxed. As long as the application follows Android's Security Best Practices, then the application should be fine -- security wise. Because internal app data is safe when the device is not comprised, there is no need to encrypt it.

When the device is compromised, there is very little an application can do to protect itself. The only real strategy is to minimize the amount of sensitive data on the device. However, EncryptedSharedPreferences and EncryptedFile seems to imply that it can protect user data even when the device is compromised, as talked about in Android's Blog Data Encryption on Android with Jetpack Security:

Why would you want to encrypt data in your app? Doesn’t Android, since 5.0, encrypt the contents of the user's data partition by default? It certainly does, but there are some use cases where you may want an extra level of protection... In the app home directory, your app should encrypt data if your app handles sensitive information including but not limited to personally identifiable information (PII), health records, financial details, or enterprise data.

But what does it mean by "extra level of protection"? According to the same Blog:

Before we jump into encrypting your data, it’s important to understand how your encryption keys will be kept safe. Jetpack Security uses a master key... which is generated and stored in the AndroidKeyStore.

So Jetpack's EncryptedSharedPreferences and EncyptedFile uses the KeyStore to generate and store the keys for encryption. This is verified by examining the source code. And this is also where the problem is.

The KeyStore is not intended to generate keys to encrypt data local to the device. As the answer to the post Android - What are the practical security benefits of using a hardware-backed keystore vs software-only keystore vs no keystore points out:

The purpose of a key store is not to restrict access to an application or application data, it's purpose is to protect the credential from being exposed during use. Since a key store will willingly leverage its knowledge to encrypt data or access sensitive application information, it's not really a challenge for an attacker to leverage as you pointed out in many of your breakdowns across all three types.

This means that, on a compromised device, a malicious program can use the KeyStore to decrypt all of the previously encrypted data. The Android Documentation acknowledges this:

If the Android OS is compromised or an attacker can read the device's internal storage, the attacker may be able to use any app's Android Keystore keys on the Android device, but not extract them from the device.

This completely nullifies any encryption done by EncryptedSharedPreferences and EncryptedFile when the device is compromised.

To recap: When the device is not compromised, internal app data is safe. When the device is compromised, internal app data is not safe, regardless of whether it is encrypted via EncryptedSharedPreferences/EncryptedFile or not.

Question:
If the above is true, then what are the benefits to using EncryptedSharedPreferences and EncryptedFile? Is there a specific scenario where EncryptedSharedPreferences and EncryptedFile can protect internal app data, as compared to their non-encrypted counterparts?

EDIT 1:
As pointed out in the comments, "internal app data" is ambiguous. Specifically, I mean the location at /data/data/<package name>, which is protected by app sand-boxing and credential encryption. Also, in terms of this question, I would like to focus on Android 10+ as this is when FBE was required. However, I am also interested in scenarios in lower Android versions too (at the time of writing, minimum API level for EncryptedSharedPreferences/EncryptedFile is 21).

EDIT 2:
After re-reading the question, I think its also really important to be clear here by what the KeyStore is. The KeyStore consists of 2 major parts: a physical component (e.g. TEE, SoC, HSM) and an OS daemon. The physical component is the thing that performs crypto operations on behalf of the OS, so no process (including the OS) can know what the key is. The OS daemon is the thing that restricts usage of the physical component. Because the OS daemon restricts usage, a malicious program (on a compromised device) can circumvent those restrictions and directly use the physical component. This is the reason why the KeyStore is not supposed to be used to encrypt data that remains local to the device. The physical component only provides the property that the key itself will not be known by an attacker, not that it can't be used by them. More information about the KeyStore can be found here and here.

Shelashelagh answered 30/6, 2022 at 20:35 Comment(21)
You do not supply your definition of "compromised", and that term has a wide range of possible definitions.Highbred
@Highbred That's fair. I was mainly thinking about root but decided to use the word "compromised" to match with the Android Documentation quote. In reality, there is a much more grey line between full access and no access, but I wanted to drive home that KeyStore is not intended to be a magical box that no-one but the real developer has access to, and therefore shouldn't be used as such (as Jetpack does).Shelashelagh
@Highbred To add on. I want to emphasize that if the device is compromised to the point that an attacker can read internal app data, then its most likely that the attacker can get access to the KeyStore keys for that app.Shelashelagh
"I was mainly thinking about root" -- even "root" has a range of possible definitions. For example, do you consider every privilege escalation exploit to be equivalent of rooting the device? "if the device is compromised to the point that an attacker can read internal app data, then its most likely that attacker can get access to the KeyStore key for that app" -- I am unconvinced about the "most likely" aspect and would go with "possible".Highbred
I think the point is less about providing absolute bulletproof protection, and more about giving the average developer an easy-to-use set of best practices for keeping on-device data reasonably secure (especially when using shared storage). And that could be important for complying with data privacy laws (which is a thing you're now required to outline your handling of on the Play Store)Pili
@Highbred You're right to drill down to the specifics. I haven't done a security audit around KeyStore, so I can't make claims about likelihood. By root, I mean full admin "su" privileges, the same type of root you get from rooting your phone. And even this gets blurry because of SELinux permissions. I do know that you can get access to KeyStore with admin privileges. So, at the very least, using EncryptedSharedPreferences (and family) doesn't secure app data when its rooted (as its commonly thought to believe). Which brings me back to, what is EncryptedSharedPreferences used to prevent?Shelashelagh
@Pili Shared storage makes sense (which is why I left it out of one of the quotes). My concern isn't with shared storage. My concern is a false sense of security that EncryptedSharedPreferences and EncryptedFile provides with internal app data. My concern is with the apparent useslessness of its functionality. Again, specifically what extra security does it provide when compared to the non-encrypted counterparts?Shelashelagh
"what is EncryptedSharedPreferences used to prevent?" -- EncryptedFile and EncryptedSharedPreferences are a bit of a red herring, as you don't need them to use KeyStore for encryption. But, in general, they are for defending against privilege escalation exploits that grant broader filesystem access but stop short of full root or anything else that would allow for KeyStore access impersonation. For example, imagine an exploit that causes an app to be marked as debuggable, so developer tools have unfettered access to that app's portion of internal storage.Highbred
@Pili I'm not a lawyer so I can't really talk about data privacy laws in a rigorous way. But we are talking about encryption not one-way hashing, which means the data that is stored is recoverable. So, if by law you are not allowed to store the data, then it wouldn't make sense that you could store an encrypted version of the data.Shelashelagh
@free_coupons_for_sale_1023 you are allowed to store it, you just have to comply with legislation about securing it - and that might be a bit vague (a lot of this legislation is) but showing that you've made an effort to keep that data secure is better than not. A lot of this might be from Google's side too (I'm just speculating) - maybe to limit their own liability they've released this library, so they can show that Android does make securing data possible and that shifts (legal) responsibility to the devs to use itPili
@Pili I know you're speculating; it just sets off alarms in my head. "make securing data possible" is confusing to me. The data doesn't need to be secured. Android sandboxes apps which means its already secure. Also, Android 5+ devices are encrypted by default (granted this doesn't mean much if the user doesn't register credentials). I've also seen this in articles too, namely this one. It implies that app data isn't secure unless you encrypt it, which is absolutely not true.Shelashelagh
security isn't a single thing though, it's multiple layers of defence that have to be defeated to compromise the device, and which limit what an attacker can do if they do manage to exploit some holes in those security layers. The "attacker" can also be the legitimate owner of the device! So when I say makes securing data possible I mean beyond the inherent security of the environment the app is running in (which can also vary depending on OS version). You can deliberately encrypt sensitive data and add an extra layer, instead of doing nothing and trusting the OS will protect itPili
@Pili The problem is that it does not provide extra security. I defer to a comment from How to Secure Android Shared Preferences?: "All of the mentioned solutions work this way: Let's secure the door with a lock. But where to place the key? Lets just place the key next to the door. Conclusion: All solutions do not provide any security - they all just use obscurity to hide data. Please be aware of this!" EncryptedSharedPreferences encrypts the data and then puts the encryption key on the device.Shelashelagh
@Pili Also, if the attacker is the device owner, then you have separate security issue at hand. Clients should never be given information that could exploit the server. Its impossible to tell the difference between a legitimate client running your software and an attacker running an attackers software. Also, if you're relying on the user not being able to access EncryptedSharedPreferences, then the user could always root their phone and get the app's keys from the KeyStore. I just don't see a concrete scenario where a user would have access to internal app data but not the keys.Shelashelagh
There's no obscurity - the keys are in the keystore. The keystore restricts usage of the keys and makes it more difficult to access them directly - it's an extra layer of security, often a separate hardware module. Look I'm not here for an argument or anything, and security isn't really my area anyway (it's extremely complex - there's a reason all these layers exist) but you seem to be operating under the assumption that any exploit gives an attacker full access to everything, and that's not how it works. A worst-case scenario doesn't make mitigating less serious attacks pointlessPili
You're right, it is not no exploit v.s. full exploit. But internal app data is protected by the UID of the calling process, and so is the KeyStore. That means if an attacker has access to read files protected by the UID, then they have either bypassed the OS's restrictions or have tricked the OS into thinking they are that UID. If its latter, then theres nothing stopping the attacker from getting access to the KeyStore. I am not arguing that it provides no protection; I am arguing that its being used as if it provides more security, without giving reason to why its more secure.Shelashelagh
Just to see if you've covered your bases: When thinking about your question, did you think about the presence of hardware security modules such as the Titan chip, found in certain Android devices, or similar "trusted execution environments" (TEEs), or the possible storage of private key material in such hardware security modules?Trichinosis
@PeterO. Yes. When the device is physically compromised there are 2 states: Before First Use (BFU) and After First Use (AFU). In BFU, the device is encrypted and already protected. In AFU, the encryption keys are stored in memory and may be susceptible to a cold boot attack. However, as of Android 11+, Ephemeral Keys are used to specifically address cold boot attacks. In the case of a compromise of the OS, then see Edit 2.Shelashelagh
@PeterO. Over the past week, I've learned a lot more about Android's security and encryption. From what I can tell, EncryptedSharedPreferences/EncryptedFile comes into play to ensure data is at rest even when the device is in AFU (this only true when the device is physically compromised). However, like I said, Android 11+ addresses the issue with Ephemeral Keys.Shelashelagh
@PeterO. To directly answer your question. Yes I've considered TEE and SoC. They are used to prevent the OS from actually knowing the raw key material and (in the case of the Titan M) to physically protect the keys in case the device is physically compromised. They are also tied to a hardware root of trust to stop a physical attacker from flashing the OS etc.Shelashelagh
Then you have brought up important points (about encrypting data that stays on device) that you should address to the developers of Android or Jetpack (or to the authors of the articles describing the Key Store). Perhaps they will respond to you on whether data that stays on device truly ought to be encrypted.Trichinosis
M
0

If device is compromised, the security of whole system is in doubt and all data might being considered exposed. If device is not compromised, the OS itself should guarantee safety of the applications, data and execution environment.

I'd elaborate on another state, the device being analyzed by a 3rd party, in many cases in offline mode -- possibly law enforcement subject or a thief.

According to docs EncryptedSharedPreferences the preferences file gets encrypted hence protect data at rest. This level of security is independent of other security aspects of the device (optional FDE or SD card encryption) and is manageable by the application developer. Using Android KeyStore should allow to use of the Android security features (such as HSM) via standard and stable API.

Answer

... what are the benefits to using EncryptedSharedPreferences and EncryptedFile?

The application developer can assure some security level for the application data via standard API.

Is there a specific scenario where EncryptedSharedPreferences and EncryptedFile can protect internal app data, as compared to their non-encrypted counterparts?

Yes, during evil-maid or offline attack on the device (or storage), EncryptedSharedPreferences/EncryptedFile can provide protection for the application data or at least raise the bar required to acquire such data to non-trivial level.

Minne answered 3/7, 2022 at 8:46 Comment(9)
There's a few things wrong with this answer. First, Android 10+ requires FBE. As part of FBE, the FBE is encrypted withe DE key which is specifically meant to protect the device against attacks that flash a new OS. Second, the device is further protected by CE. If the user hasn't registered CE, then its already game over (the attacker can directly access the phone through the OS). All of this means that the device is already protected at rest.Shelashelagh
Further, think about this: the phone's DE keys is protected by the KeyStore (e.g. TEE/SoC). So, if the attacker can get access to the DE, what stops the attacker from getting access to the key's stored in the KeyStore by EncryptedSharedPreferences? And for lower level android versions that use FDE, again the phone is protected by CE at rest. Also, Evil Maid Attack is a misnomer. It refers to altering the device in some deterministic way to manipulate the device owner into giving credentials (or some other thing). But first, the attacker must already have exploited the device to manipulate it.Shelashelagh
And, lastly, in all cases where the phone does not have a physical key store (i.e. a software based key store), then all of the keys are stored on disk. If an attacker can read the contents of the disk (which EncryptedSharedPreferences presumably protects against), then the attacker could just read the KeyStore's keys and decrypt all data encrypted with those keys.Shelashelagh
I believe that FDE requirement does not apply to SD cards by default since as I recall can be read by regular PC without any need for decryption and user can choose if application data will be stored on device internal memory or SD card.Numerous
I believe that evil-maid terminology would also refer to the situation where 3rd party will be available to temporary capture the device for cloning or other examination, but I accept the your objection.Numerous
It is true that SD cards are not encrypted by default. But I never talked about SD cards. Specifically I talked about internal app data that exists in the directory /data/data/<package name>. If you read the comment chain on question, you'll find that I agree with use of encryption on shared storage (unencrypted SD cards must be considered as shared storage). The problem, and the question, is that I can't find a reason to use extra encryption on internal storage (which is already encrypted by FBE and sandboxed by the OS).Shelashelagh
You did not talked about SD cards, but the encryption technology discussed are provided by Android SDK and are at disposal for the developer without being strongly tied to the android version, system configuration or user settings. So I believe that answers to your questions are relevant.Numerous
The question: "Is there a specific scenario where EncryptedSharedPreferences and EncryptedFile can protect internal app data, as compared to their non-encrypted counterparts?" The question specifically asks about internal app data, not the SD card.Shelashelagh
Agreed, I've missed the internal data requirements. Sorry. Btw internal app data is a bit ambiguous term, you'd better to describe it as device internal storage in this case.Numerous
C
0

Based on my knowledge and expereince in this part.

EncryptedSharedPreferences came to secure user data even in rooted devices.

When you create a SharedPreferences object in your implementation, a file is created in a directory called shared_pref, and it would include the filename you passed in your code implementation.

This shared_pref folder is located in data/data/your package name.

This directory is accessible if the device is rooted, so data inside could be exploited.

It's easy to read the preferences file as it's a map file, with key and values like the following:

enter image description here

while, if you used EncryptedSharedPrefences, your key and value are encrypted by default, so even the device is root no data could be exploited.

like the following:

enter image description here

If you need to check your sharedPref files, you can do it from Android Studio

  1. Open Android Studio
  2. Run your application on an Emulator
  3. on Device File Explorer(Bottom Right of the Android Studio)
  4. Find your package name within the data/data directory.
Coenesthesia answered 8/7, 2022 at 14:59 Comment(6)
This is not true. Root can access the KeyStore.Shelashelagh
Further, this is addressed in the Android Kernel Security overview: "Encrypting data with a key stored on-device does not protect the application data from root users. Applications can add a layer of data protection using encryption with a key stored off-device, such as on a server or a user password. This approach can provide temporary protection while the key is not present, but at some point the key must be provided to the application and it then becomes accessible to root users."Shelashelagh
Also, see here for a breakdown of the different "types" of KeyStores, when each is vulnerable, and also what a KeyStore is intended for. Quick answer: to prevent the extraction of keys, not their use on the device. Read my second edit too; it explains how a compromised OS (e.g. rooted OS) can use any application's keys in the KeyStore to decrypt data.Shelashelagh
And taken directly from the question itself, the Android Documentation acknowledges this: "If the Android OS is compromised or an attacker can read the device's internal storage, the attacker may be able to use any app's Android Keystore keys on the Android device, but not extract them from the device."Shelashelagh
Simply, There is no absolute security If you are able to encrypt the data, and you know that the root device has KeyStore access, you should do this. You increasing layers of security as much as you can. EncryptedSharedPreferences saves keys and values in the KeyStore, at least it would take time to be able to get the right keys to decrypt the keys and values of the shared_pref file. So, I beleive that my answer carries some of truth about the benefits of EncryptedSharedPreferences library, it's just added security layer.Coenesthesia
Doing so is security through obscurity. There is no "hard" cryptographic problem that the attacker must solve in order to get access to the data. All the attacker has to know is that the data was encrypted with the KeyStore and they immediately have access to the data. "Layers" of security is fine but obfuscation is not security.Shelashelagh

© 2022 - 2024 — McMap. All rights reserved.