All WebViews of an Android app share (among other data) their set of stored cookies. I want to separate the cookie storage, i.e., every WebView should have their own set of cookies.
Therefore, I am looking for a way to retrieve all cookies including meta-information (Expire date, flags etc.) from a WebView, save them separately and set them again when needed. CookieManager has a method getCookie(), however, it just returns value and name of currently valid cookies without any meta info (as discussed here).
Android WebView stores cookies in an SQLite3 database on disk. Apparently, the only way to gain the full cookie information is to have a look at the on-disk cookie store. It would be possible to parse the SQLite3 database and use CookieManager's setCookie() but then all encrypted values would be lost. So my idea was to copy the whole database file and exchange (i.e., rename) the file as needed.
Potential problems of this approach:
Synchronization issues: I don't have access to any locks the system may use for access to the cookie file.
Even if I try to rename the file ignoring the first problem, the database is only read upon start of the app. Afterwards, all cookies (both old cookies read from disk and new cookies added during runtime) are kept in RAM. I would need to force a reload from disk, but the API only offers sync in the other direction, i.e., from RAM to disk.
Where can I find the code that loads the cookies from disk initially? Android SDK's CookieManager.java is an abstract class, where do I find the actual implementation? It may have valuable insights on the issue.
For reference:
A member of the Chromium development team confirmed that it is currently not possible to separate the cookie storage within an app.
Related
I am building a React Native application and I need to save some sensitive data like a token and a refresh token. The obvious solution is to save that information using AsyncStorage. The problem is the security level of the AsyncStorage.
AsyncStorage provides a way to locally store tokens and data. It can
be, in some ways, compared to a LocalStorage option. In full
production applications, it is recommended to not access AsyncStorage
directly, but instead, to use an abstraction layer, as AsyncStorage is
shared with other apps using the same browser, and thus an
ill-conceieved removal of all items from storage could impair the
functioning of neighboring apps.
https://auth0.com/blog/adding-authentication-to-react-native-using-jwt/
In a native app, I would go for Keychain in iOS and Shared Preferences in private mode in Android.
For what I read in the documentation provided by React Native:
On iOS, AsyncStorage is backed by native code that stores small values
in a serialized dictionary and larger values in separate files. On
Android, AsyncStorage will use either RocksDB or SQLite based on what
is available.
https://facebook.github.io/react-native/docs/asyncstorage.html
They never talk about the security of that data.
It is the best solution create a module for Android (that uses Shared Preferences in private mode) and another for iOS (that uses Keychain) to save the sensible data? Or it is safe to use the AsyncStorage methods provided?
Just digging into the React Native code, I found the answer.
Android
The React Native AsyncStoragemodule implementation is based on SQLiteOpenHelper.
The package where all the data classes are handled: https://github.com/facebook/react-native/tree/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage
The class with the instructions to create the database: https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/modules/storage/ReactDatabaseSupplier.java
By the Android documentation, the databases created by the application are saved in private disk space that's associated application, so it is secure.
Just like files that you save on the device's internal storage,
Android stores your database in private disk space that's associated
application. Your data is secure, because by default this area is not
accessible to other applications.
Source
iOS
In iOS the AsyncStorage values are saved in serialized dictionary files. Those files are saved in the application NSDocumentDirectory. In iOS all applications live in their own sandbox, so all files of one application are secured, they cannot be accessed by the other applications.
The code in iOS that handles the AsyncStorage module can be found here: https://github.com/facebook/react-native/blob/master/React/Modules/RCTAsyncLocalStorage.m
And as we can see here the files used to store the values saved by the AsyncStorage are saved under the NSDocumentDirectory (inside the application sandbox environment).
Every App Is an Island An iOS app’s interactions with the file system
are limited mostly to the directories inside the app’s sandbox. During
installation of a new app, the installer creates a number of
containers for the app. Each container has a specific role. The bundle
container holds the app’s bundle, whereas the data container holds
data for both the application and the user. The data container is
further divided into a number of directories that the app can use to
sort and organize its data. The app may also request access to
additional containers—for example, the iCloud container—at runtime.
Source
Conclusion
It is safe to use AsyncStorage to save user tokens, since they are saved under a secure context.
Please note that this is only true for Android devices without root and for iOS devices without jailbreak. Please also note that if the attacker has physical access to the device and the device is not protected. He can connect the device to the mac laptop and extract the documents directory and see all the contents saved under the documents directory.
AsyncStorage saves key-value pairs as a plaintext JSON file in the Documents directory. It does not encrypt its contents.
This is a security issue (at least on iOS) because it's possible for an attacker with access to the device to obtain a dump of the contents of the sandbox and trivially extract any data saved through AsyncStorage.
This used to not be clearly stated in the docs for AsyncStorage.js, but it is now:
https://github.com/facebook/react-native/pull/8809
Also see: https://stackoverflow.com/a/38398114/1072846
If someone wants the additional step of having the data encrypted, you might want to look at this: https://github.com/oblador/react-native-keychain
It uses facebook conceal internally.
I really recommand you to use a library like react-native-keychain to store private data in react-native
For Android API level:
16-22 use Facebook Conceal
23+ use Android Keystore
You can use it like that:
// Generic Password, service argument optional
Keychain
.setGenericPassword(username, password)
.then(function() {
console.log('Credentials saved successfully!');
});
// service argument optional
Keychain
.getGenericPassword()
.then(function(credentials) {
console.log('Credentials successfully loaded for user ' + credentials.username);
}).catch(function(error) {
console.log('Keychain couldn\'t be accessed! Maybe no value set?', error);
});
I want to store some configuration in my app (like the URLs to my web services), similar to a config.properties for Tomcat or Jetty.
It seems that I have to use SharedPreferences, 2 problems:
If I want to use PreferenceManager.getDefaultSharedPreferences(context) what should be the file name and where should it be in the project?
I tried getSharedPreferences("config.properties", MODE_PRIVATE) after creating config.properties in the assets folder but that doesn't work, what is the correct way to do? The file contains pairs like key=value.
Also what is the most secure way to save sensitive config values such as credentials (like AWS keys)?
If someone form Google is reading me, your doc is pretty vague/non-existant (or hard to find) about that stuff.
Thanks
1/2)You don't pre-store shared preferences. They exist on disk only (not in the apk). If you need them to exist in the apk, use a different file format (like json) and transfer them to shared preferences the first time you're run.
3)The best way to store sensitive data is off-device on a server and transferred only when needed via an HTTPS web service. Anything else can be trivially found by anyone with any knowledge of reverse engineering.
Is it possible to access my app's localStorage in other way then via this app?
I am making an app which uses localStorage and I want to be sure there are no possibilities that someone can access my data.
Thank you for your attention and answers.
Phonegap applications are executed on a UIWebView, which uses WebKit engine for all the web-related stuff.
All the navigation data, such as the local storage, caches and so on are stored in the app's data store (a sandbox) and thus can't be accessed from any other apps unless you provide the methods to do so, ie: shared keychains, URIs and so on.
This is built into the iOS security system and there isn't an official way of accessing the data via the public APIS (which doesn't mean it's totally secure). If you are storing sensible information that you don't want to be accessed you should always encrypt such data. Refer to this document if you need more info on the topic.
By default no one can access the data stored in your app except your app itself. In the info.plist file you can add an entry
Application supports iTunes file sharing
If you add this field in your info.plist and set it to YES, only in that case the user can access the data stored in the documents directory by connecting the device to the iTunes.
I'm looking for a way to be able to encrypt all data written to the WebView cache. Since it has been deprecated, I am attempting to avoid using the CacheManager. My current strategy would be to catch all attempts to write to cache and encrypt the data just prior to writing it and to catch all requests for data from the cache so that I can decrypt the data before returning the data requested.
I guess it is possible to encrypt all your data. But it is probably better practice and security to just clear the data it after use. You are correct that you should not use CacheManager because it is deprecated.
Android Security designs recommends clearing the cache:
If your application accesses sensitive data with a WebView, you may want to use the clearCache() method to delete any files stored locally. Server side headers like no-cache can also be used to indicate that an application should not cache particular content.
from here:
http://developer.android.com/guide/practices/security.html
But if you want to encrypt the data you will have to do it manually. So you would need to go to the directory where Android stores its cache and encrypt it yourself. There are different ways to do this depending on what you are trying to accomplish. How and when you do that will be up to you.
Off the top of my head, if you are trying to make a web browser application. the best way to do this is to create a wrapper class for the CookieStore or CookieManager class which could be found here:
http://developer.android.com/reference/java/net/package-summary.html
I hope this helps
Currently I'm working on a solution that shall able to encrypt the WebView cache. I'm brainstorming some possible solutions, according to you're thoughts...
Some possible (or not possible) Solutions I faced for now:
1. GoT hook read and write of libchromeXX.so
Pro
Deterministic encrypt and decrypt the cache. There won't be any unencrypted data on disk.
Cons
Very risky (possible architecture / device specific issues in field, possible android version specific issues, possible webview
implementation specific issues)
2. Listen with inotify for fs changes and encrypt jit (just in time). Decrypt on next app launch
Pro
Only "public" API
Cons
Some android devices might not support "inotify"
At runtime the data can be manipulated (sure only with root / system uid and if attacker this permission he might hook stuffs in
our process anyway)
3. Create hash over all data or last modified / size combination and store seperately
Pro
Only "public" API
Maybe faster than encryption
Cons
Only verifies if data was manipulated
The digest must be stored somewhere?
4. Somehow use ETag mechanism to validate the data
This I researched not that deep right now, but potentially the ETag might represent the hash of a particular resource and we might verifies if the hash matches to server provided digest. We would have to iterate through the cache and search for ETag and resource pairs or is there a browser feature out of the box? I guess not :(
Pro
Validation might be out of the box if browser supports it
Cons
Potentially not working or not the intended usage of ETag
Isn't there any mechanism that verifies integrity of cached resources?
I want to know how safe it is to pack the database with the application in android. Can the database be easily accessed by the users? As the database that I have will have data which I dont want to be hacked by users for misuse, what is the best way to protect the database in mobile apps?
Also my application would use web service(contacting my own website) e.g. http:\www.mysite.com/services/xxx
My site will in turn return some data to the mobile app. If someone decompiles the java code(in apk), he will easily get access to the URL i am using for web service. How can i protect my data on website to be attacked by malicious users. If anyone gets to know the URL, he can simply type that URL in browser and get all data in json format which i dont want as that data can be quite sensitive. Even if I keep it encoded, then the user can get to know the encoding from the java code(which he gets after decompiling apk).
How to keep my DB safe from being misused?
If my application is to show the local places like restaurants, bars etc on mobile should i always fetch them from the website using web service or provide a local database with these details so that information can be fetched quickly. In this case , I can provide a UPDATE web servcie which will update the local database. But security of local DB is of great concern to me.
Can anyone please suggest where to keep the DB and how to safeguard it?
Rgds,
Sapan
Local databases and your apk file can be read by any rooted device easily. This tool can even decompile your resources as explained in this youtube tutorial (I never tried that myself actually).
So you would have to store your data encrypted in your database and decrypt it form your application code to be sure that noone can access it by simply getting the database form the data directory of his device.
You shouldn't put your sensitive data (like passwords etc) in the resource folder, because it can be decompiled, put it in your code.
Now some words to your JSON API. Hiding the URL is not enough, since the user can track your requests easily by a sniffer and get that anyway. You should provide a authentication mechanism to protect unauthorized access and also protect your communication by SSL. (E.g. using HTTP authentication - makes only sense when your server provides SSL.)
This are the things you should think about and decide yourself how sensitive your data actually is.
As far as I understand you're going to:
Pack initial DB in your APK file (say with res/asset folder)
During first run explode DB file from res/asset to application data folder
Then from to time fetch data into DB from website/webservice
In this case there are basically 2 vulnerabilities (stored data I mean):
Initial DB image, since it's packed with APK (which is in real life just ZIP archive), so anyone can unpack and see what's packed in your DB
DB file stored in application data folder (usually /data/data/MY_APPLICATION_PACKAGE/databases). This folder is accessible on rooted device, so again your data can easily be screened
The only option to be secured is to encrypt your database content. Easiest way to do it to store sensitive data in BLOBs (in form of XML of JSON) and encrypt/decrypt those BLOBs after/before actual usage of certain records.
Myself personally did it in my app - and it works well.
check this links for protecting your apk file for decompile
How to make apk Secure. Protecting from Decompile
Protecting Android apk to prevent decompilation, network sniffing etc
decompiling DEX into Java sourcecode