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?
Related
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.
I saw similar questions but they don't fulfill my requirements.
I have an app that time to time needs to be updated from a web service. Data contains such fields as url, description, title. from 200k to 400k entries.
It is used locally and search among this data is performed quite often (depending on user's activity).
Data shouldn't be accessible by users and search needs to be as quick as possible. I know that there is no way to make it 100% unreadable, everything can be reverse-engineered and decrypted (I have to keep the encryption key on a phone). My goal is to make it as difficult as possible.
I have few choices:
1. encrypt data on server and send it as binary file to phone. Decrypt it every when needed
2. also send data as file. Read it, store to local database
3. Get it as JSON (probably encrypted), store to database or file
There is an advantage of using JSON because it will be easier to implement updates of difference between local data and remote.
Also there is a question about databases. Should I store all entries encrypted and decrypt it every time I want to find something? It might affect phone's performance.
There is also one more possible layer of protection - make encryption keys dynamic. Get a key from server once a day, re-encrypt stored data, the next day key changes. However I suppose it is an overhead. Tell me if it isn't.
What option would you choose? Are there any better solutions?
P.S. database is going to be updated daily.
Thanks
I'd store the data in SQLite, but also make the decryption scheme more intricate, using at least two keys... one, stored in the shared lib, other downloaded from the service and unlocked with that key.
This also plays into your thought up strategy - you can have one 'device' key, which comes with the APK - embedded as a hardcoded byte[] in the .SO, and another 'daily' key which will be used to open 'daily' data updates. Although, i'd rather be using the 'daily' key in a bytearray format, never saving it in any form on the device except having it decrypted in memory only for duration of it's use. This would be an upgrade to what I did, where i just saved that key as a base64-encoded devicekey-crypted string.
Working with SQLite is fairly easy, which you can see here - Android Database to Array.
I did something similar to what i'm explaining (without the updating daily keys however) here - not decrypting what I crypted.
Give it a look and discuss :)
I'm making an application where users can store data on the device. I was thinking about using database storage. But I've been reading somewhere that it is possible to manipulate data that is stored locally on the device. So what would be the best way to avoid such "attack" on the data? I have been thinking about encrypting each field in the database, but again then I have to store an encryption key on the device as well(?), which again I guess can be located? So does anyone have any other ideas/improvent of my thoughts?
Thanks for any help!
I'm looking for a way to make it a big challenge
Challenge accepted :)
The first thing you should do is to store the data in your app directory since it is not readable for the user / other apps on a regular device. Links to app data con be obtained from Context e.g. Context.html#getDir(). The directories you get from Environment are public.
That prevents average users from getting the data. But a lot of people have rooted devices and can access the data without problems, so that is still pretty insecure.
To make it a lot harder you'll need encryption. Any strong encryption that is not fundamentally broken like WEP will do. Using encryption you force the user to find the key (and encryption method) since the encrypted data can't be decrypted in reasonable time.
That leads to the problem of having a secret key somewhere available to your app but not the user. And this is the part where you need to get creative since there is no secure way to do that.
The simplest way is to put the key in plaintext in your app code. Like private static final String SECRET = "42". By simply having encrypted files you will already stop most users from digging further since at that point you need some programming skills to read the data.
If the user has those skills he will likely start to look at the code of your app (using e.g. dex2jar + jd-gui). You should do the same if you want to know how hard it is to reverse engineer your app.
Understanding the code / finding the encryption method + password will get harder if you use proguard to obfuscate the code because app internal class-, method- and variable names will be shortened to A.B.c(d) like code. But method calls to Android's API can't be renamed since you would need to rename the methods on the device. Also string constants like "42" won't be changed.
The next step of making it harder is to replace that constant by something dynamically generated by your code. The basic example below for example builds the password by dividing numbers by two. The advantage when using this approach is that the password is no longer stored in plaintext and you need to understand / reverse engineer the method that converts the data into the password.
private static final byte[] password = {8, 4};
private String getPassword(byte[] data) {
StringBuilder sb = new StringBuilder();
for (byte b : data) {
sb.append(String.valueof(b / 2));
}
return sb.toString();
}
// returns "42" if I did not make a mistake
The next vulnerable point is that calls to device crypto APIs can be easily located (since they can't be renamed) which makes it a lot easier to figure out where to look for the encryption. If you don't want to write your own crypto method which I would strongly suggest you don't because a slight error in here may corrupt data or break the complete encryption.
That problem can be hardened if you use reflection for example (calling methods by supplying the name of the method / class supplied in a String). That String can as well be obfuscated like above example did with the password.
If you do all that and don't use a method not as simple as this one you can make it really hard. dexguard for example can do that for you but it's not free and has the problem that the same method is used for many apps and a lot more people will try to break that than your custom method.
Finding a good method to hide information in your app that is used to generate a key and a method to hide the key generation & encryption / decryption is best figured out by yourself so the method itself is not public knowledge.
You can use combine a lot of techniques to hide the information like moving parts of that into native code so Java guys like me have a hard time or use a network connection to let your server do some work.
But in the end it's all Security through obscurity and all the extra security measures don't benefit the user but require extra processing time & additional app size.
So what would be the best way to avoid such "attack" on the data?
Do not put it on the device.
I want to make the data secure against the user of the app.
Then do not put it on the device. It is the user's device and the user's bandwidth, and hence it is the user's data.
But I'm looking for a way to make it a big challenge if the user finds out he/she will try to do so.
Simply using a database or something else on internal storage will stop 99% of Android device users from accessing your data. There is nothing you can do to stop the remaining 1%.
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
My application would be frequently connecting to the web service to get some data in json.
Is there a way this data can be encrypted on server side and decrypted on application side so that data transferred is secure and safe?
Also, if the applicaiton comes with its own database (sqlite db file), is it possible for anyone using this application to look at this database (tables, fields and content)?
Regards,
Sapan
Your easiest option for transferring the data encrypted is to use SSL (i.e. https) for the communication between the app and the web service.
If you need to set up your own self-signed certificate for the server (instead of buying one) you might have problems getting android to talk with it, but it's doable. See this SO question for tips.
Regarding reading the database, it might be possible. I would assume that an attacker that got access to the phone could read the database, if they were determined enough. If you want the data to be really secure, you would have to store the database in an encrypted file and require the user to enter a password each time they open your app.
You have to decide how much security you really need.
You should definitely go for SSL encryption of the data when you transfer it over the network, though.
You can use crypto to encrypt/decrypt json in both android and server.In it very simple and secure. Using Base64 is not a efficient way, because anyone can decrypt. In this, you can use a secret key to encrypt and decrypt the String. If using wrong key to decrypt, the output will be wrong.
http://www.androidsnippets.com/encryptdecrypt-strings
I use Base64 encoding and decoding to encryt data over the network.
Depending on the type of webservice you are using, it will or will not have Base64 encoding and decoding. You can always google for code made by others.
Depending on the Android version you are targeting.
From API level 8 and up: http://developer.android.com/reference/android/util/Base64.html
For lower: http://www.frankdu.com/notes/2011/01/27/base64-encoding-with-android-2-1-or-earlier/
You could also write your own encoding and decoding systems of course. ;)