I wonder about shared preferences security.
Is it possible to get access to sharedpreferences, even if they were created in MODE_PRIV (0) ?
Is it possible to list all sharedpreferences available and then fetch all settings from other apps?
Is sharedpreferences good place to put sensitive data, such as password or auth token?
Thanks
Shared Preferences are stored as a file in the filesystem on the device. They are, by default, stored within the app's data directory with filesystem permissions set that only allow the UID that the specific application runs with to access them. So, they are private in so much as Linux file permissions restrict access to them, the same as on any Linux/Unix system.
Anyone with root level access to the device will be able to see them, as root has access to everything on the filesystem. Also, any application that runs with the same UID as the creating app would be able to access them (this is not usually done and you need to take specific action to make two apps runs with the same UID, so this is probably not a big concern). Finally, if someone was able to mount your device's filesystem without using the installed Android OS, they could also bypass the permissions that restrict access.
If you're concerned about such access to your preferences (or any data written by your application), then you will want to encrypt it. If you are that concerned about them, you're going to need to figure out exactly how much protection is necessary for the level of risk you see. There is a very extensive discussion about this in Application Security for the Android Platform, just published in December 2011 (disclaimer: I'm the author of this book).
SharedPreferences are nothing but XML files in your phones /data/data/ folder,So any application or user with superuser privilages on a rooted device can access your SharedPreferences, even if they were created with MODE_PRIV
Still there is a way to protect it from everybody...
Please checkout this link.
Here you can store data in pref with encryption,the class is self explanatory and very easy to use.
https://github.com/sveinungkb/encrypted-userprefs
As said by others anyone can access it but in this case no one can read data inside it as it is encrypted. So its secure.For Utmost security my suggestion will be to generate the key used for encryption at run time rather than hard coding it. There are many ways to do that :)
Normally, no, they cannot be accessed by other apps, however, you should note that SharedPreferences are stored as XML files in the /data/data/ directory, which essentially means that any application with superuser privileges on a rooted device can access your SharedPreferences, even if they were created with MODE_PRIV
Is it possible to get access to sharedpreferences, even if they were created in MODE_PRIV (0) ?
By code No. But you can retrieve application file if you have super user privileged.
Is it possible to list all sharedpreferences available and then fetch all settings from other apps?
If you are super user(rooted devices) then you can pull all private files of the app.
Is sharedpreferences good place to put sensitive data, such as password or auth token?
No. It can be easily hacked. If you want to put any sensitive data in shared prefrence file you can encrypt the data and store. You can store your encryption key in NDK/server.
Related
I'm trying understand which is the best way to store sensitive data in Android. In my app i want to insert a classic in-app-purchase model with some coins. My problem is that i'm not sure how to implement this correctly.
The initial idea was to simply use my firebase database, store the number of coins for every user and fetch the data every time the app is launched. This way I can easily detect some inappropriate usage but my users are forced to use the internet to play.
Looking at the documentations, I found this. Can this be a solution? Can I save in the internal storage the number of coins, maybe with some type of encryption, to avoid root user to modify the file? Then when the internet is on I can double-check the local stored variable with the the one in the database.
Thanks
Not an "easy" task.
Technically, you can create a SecretKey and encrypt data, so no normal user will be able to reproduce. If your concern are root users, You are kind of out of luck, as he can hook into your app while it is reading/writing that value.
But to store it online is not a solution in itself. You have to answer questions like: "Do you trust any server input"?
"How to make sure just paid coins are added"?
Have you had a look at Google Play billing?
it provides safe way's to determine if somebody paid or not.
This will require to be online.
If you have a sensitive data to save you can use sqlcipher database .. the good with it that it encrypt the database file itself so even the root user be able to get the database file he will not be able to decrypt it if you use a secured encryption algorithm.
you can find more about sqlcipher here
https://www.zetetic.net/sqlcipher/sqlcipher-for-android/
Since I assume you will grant your app a reading permission of your sensitive data and all writing processes should be reserved server-side, I would not recommend storing the data in a file on a phone, though every encryption can potentially be passed.
Maybe you already have heard about SharedPreferences, which is a good solution for let's say Preferences the user selects and that only shall affect his particular installation of your app. The difference is, that values are not stored in an external file, so not that easy accessible, BUT your app needs to write them, due only the app can access them directly (also your server can't). I am not aware of how your sensitive data is used at all but I would also not use SharedPreferences since it's injective-prone.
Official docs about SharedPreferences.
If security of your data (speaking of Confidentiality, Integrity, Authentication) is your No. 1 priority, simply don't store your sensitive data on the users device. Focus more on creating an API that ensures secure and performant passing of the relevant bits of your sensitive data. Hope this helps to give you a view of which way to go and which to walk around.
I have a problem. I am using xyz.db file and which is stored in asset folder. I am copying all data from xyz.db to application db which is stored in data/data/com.xyz/abc.sqlite in storage folder. Now I want to secure asset's xyz.db file. Because It can be easily extract from apk by reverse engineering. Please help me to secure my asset folder's database file.
You can perform the following to make it relatively difficult to access data in DB.
Password protected zip file to contain db which at runtime should be extracted.
Encrypt the file with symmetric key and again at runtime decrypt it.
Utilize sqlcipher that performs encryption for Data at Rest.
In both the above cases you will need to worry about storing the password or key. There is no sure shot way to protect the file but the above would require more effort and should be added as basic protection.
There's no final solution to your problem.
Any technique you'll use can be beaten by a determined skilled attacker.
You have to accept that if you want to store database xyz.sql in your apk file and you later want your app to use it, then it will be also possible for someone that reverse your app to retrieve it. Basically just because the plain text information at a certain moment will be available on the phone.
Hope i've been clean enough
Keep security in mind
As usual in Android the access rights of the database file determine who can use your database. If you follow the standard way presented in the following posts of this series, your database file will be located within the private directory of your app. This means that your app owns the database file and no one else can access it. Even using the other less common ways to create the database you can only grant access to the file. Thus others can access all of your database or nothing. There is no middle ground.
Still: You should never rely on data being safe from prying eyes in the database. Any sensitive data should be encrypted. Very sensitive data should not be stored on the device at all. Keep in mind that if the device gets lost, any misbehaving finder of the device can gain access to the database file as well as to your app. On a rooted device all files can be read. Apps like SQLite Editor make it easy to read even sensitive data – if they are not encrypted:
In cases where data privacy is of utmost importance, you have to revert to secured services or force the user to enter a secret every time before encrypting and storing the data or reading and decrypting them respectively.
source
Is there a way user could mess with the shared preferences values without the help of my app? E.g. can I store license details here and not worry about user extracting and copying the license key?
Its really easy to access the shared preferences.
All you need is a file explorer with root access, they are saved in an xml file in /data/data/YOUR_APP_NAME/shared_prefs/YOUR_APP_NAME_preferences.xml
For licencing you should either use google play's licence check or implement your own checking on a remote server.
If the context of the shared preferences are private (you define it when you create) only with root access it is possible to access them, without being the application who created.
Shared preferences are stored inside the app's space, when you uninstall the app, the preferences are also gone.
So normally users cannot get these values, they are stored privately.
However, with root access and a simple memory search app, a user could be able to access the data. (It is always better to store such things server side.)
I have Global Variable in my application. This is something I don't want to store, but which the user should be able to access whilst the app is running. All works.
My question is, what security implications does using a global variable have? Is it accessible from other apps?
Global variables cannot be accessed by other apps , the only case if you have rooted devices and some malicious app (low-level) can access memory , create dump of the memory used by your application and than search for your variable, but I am not sure that it will be easy even with root access.
But anyone can decompile your APK file into the smali code, and find this variable easily.
If you data is really sensitive there are some ways you can protect it.
Encrypt it with you application signature and when you need decrypt it. But it still can be hacked via getting public key from app signature and so on.
Do not store it on a device (inside you app like global variable) at all, parse this variable from the server, furthermore using SSL connection.
By default shared preferences are not accessible by other apps,as well as database, if you are not using Content Provider. But it is quite easy to get you app data with root access.
I would prefer second variant, everything stored on device can be accessed much more easier than if it is stored on the external storage.
But even if you are parsing data from the server, keep in mind that different network attacks come into play.
Also if you data( variable) is the same for all apps and if stolen all resources will accessible consider using something like temporary token or other mechanism that has expiration time.
P.S.
Android is running on the linux based kernel, all secure mechanism are applicable. So each process has it own memory address space and doesn't know about any other process in the system (generally).
No, a global variable couldn't be reachable from another application.
As I understand it, it's possible to retrieve data stored in SharedPreferences. Therefore it isn't safe. Could anybody advice me on a way to completely secure the data? I know it's possible to encrypt and store the data, but I'm wondering, is there any other way?
Data stored in SharedPreferences, if created with Context.MODE_PRIVATE, is only accessible to your own application.
Though, if the users phone is rooted, then the data can be read by root applications (even if created with Context.MODE_PRIVATE).
There is no way to avoid that, ever. But you can take precautions such as encrypting the data in SharedPreferences.
A good example of this is the SecurePreferences library: https://github.com/scottyab/secure-preferences
Shared Preferences are stored as a file in the filesystem on the device. They are, by default, stored within the app's data directory with filesystem premissions set that only allow the UID that the specific application runs with to access them.
So, they are private in so much as Linux file permissions restrict access to them, the same as on any Linux/Unix system.
Anyone with root level access to the device will be able to see them, as root has access to everything on the filesystem.
If you're concerned about such access to your preferences (or any data written by your application), then you will want to encrypt it. You can google it out.
Try this https://prashantsolanki3.github.io/Secure-Pref-Manager/ to easy work with shared preferences, it also encrypts the key and value before saving it in the preferences.
Sample code to save a value:
SecurePrefManager.with(this)
.set("user_name")
.value("LoremIpsum")
.go();