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%.
Related
I don't understand what the hacker can see and cannot see when he enters in a mobile app, for example android. He decompiles the .apk, then sees some .class files. If for example, I encrypt a key/value pair in a file, I still need to call this key from the code, and if the hacker can see the code, no matter if the key is encrypted, he will know which key I am calling?
My goal is to keep some encrypted string in my app, for example the twitter account Id of my app.
Some topics talk about " a private key to read, what was encrypted with a public key ", but if I use them, I still need to store them somewhere in my app...
Don't completely understand your requirement but the rule-of-thumb is always assume that client is not to be trusted.
You have to ensure that
All decryption should be done in your server (which you trust).
The client should never be able to access the decrypted data (unless you want it to). Hence whatever part of your code that needs to directly access the decrypted data should be in the server.
The client should have only the encrypted data (if it must store data).
The client should not be able to access the private key you used to encrypt the data.
If in your case your client must be able to access the critical data directly, then your only resort is to use obfuscation techniques (Basically hiding your data/code, to make it hard to find/understand). Of course all obfuscation techniques can be defeated eventually by a determined hacker. You have to decide how valuable your data is, what are the probabilities a hacker will try and access your data.
To take an extreme example : storing your twitter account and password using obfusucation is very bad. Storing a twitter-url- might not be so bad.
you can get your keys from server while launching app. and also dont manage in app purchase detail in sharedPrefrence or Sqlite. because in rooted device user can see that data file from root browser or sqlite editor application so user be able to change value.
A very determined person can crack it, but it's a major pain to crack encrypted strings and will stop most hackers. Especially if you obfuscate your code with something like ProGuard.
Answer to a similar question for details on how to encrypt
Reverse engineering is a great problem for android apk. Anyone can easily generate code from apk file using dex2jar and jd. Proguard can gives little bit security by changing the variable/method name. Problem is .so file. As an example, i have a so file which has a encrypt and decrypt method in it. If someone get my apk then he can easily get the so file and by creating a new project with same package name (not hidden in native loading class) he can use the functions without any problem.
Is there any solution to prevent this?? Is there any way so that i can identify my project from native code and reject the request if it comes from invalid project? Eclipse sign the apk with a key-store and password. Can i check the sign information from native code??
My 2 cents are that Proguard is just a basic obfuscator(till a point). There are many other services/tools(which might not be completely free) but do good obfuscation, app integrity protection, Tamper detection and Tamper defence etc. Check out Arxan and DashO Pro.
You might try to use them for more protection. They even work with rooted devices. Hope this helps in someway.
The problem
This is a classic problem with any intermediary bytecode language: JVM languages (Java, Groovy, Akka, etc.), CLR languages (C#, ASP.NET, etc.) and more. Since the procedures to compile the source code to its intermediary bytecode are well-documented and fairly straight-forward, it isn't all that difficult to reverse engineer the bytecode back into source.
As #Shobhit Puri has already pointed out, a good obfuscator will help deter most would-be attackers from expending the energy to decompile your bytecode. But any determined attacker with enough skills will be able to reverse engineer any obfuscated code (please note that there are many high quality Java de-obfuscators out there...) you can generate.
So how does one mitigate this?
Your best bet is to store any sensititve resources or business logic on the server, and have the client (your Android app) access those resources or invoke that business logic in a defensive way. By "defensive", I mean you code the client in such a way that any attacker who successfully obtained your full source code wouldn't be able to ascertain anything meaningful with it.
For instance, instead of:
// Get password from user input:
String password = getUserInput();
// Make sure password is correct.
if(password.equals("12345") {
// Grant access to the system
} else {
throw new SecurityException("Blah whatever");
}
You have this:
// Get password from user input:
String password = getUserInput();
// Make sure password is correct.
String correctPassword = passwordService.fetchFromServer();
if(password.equals(correctPassword) {
// Grant access to the system
} else {
throw new SecurityException("Blah whatever");
}
If an attacker were to get access to your source code, and you provide access to the password somewhere on the client-side (even if its encrypted), eventually they'll figure out how to break in. But if you fetch the magical password from the server, and never reference its value anywhere on the client, then they now need to break into your server to get access to it.
Then all you have to do is properly secure your app server, and for that you have excellent prospects like:
Apache Shiro
OWASP ESAPI
Webcastellum WAF
Spring Security
...and countless more; welcome to the world of websec
Note that in my code example above, ultimately there is no perfect defense against a skilled-enough attacker. For instance, a skilled attacker could sniff the network traffic between the client and the server during the time that the passwordService#fetchFromServer() call was made. If the password is returned as plaintext, voila - they have it. Even if the password is returned using SSL or some other strong encryption, your client will need to store or access the private key for that encryption somewhere locally. Once they have the private key, they'll be able to access the password. All this to say:
There is no such thing as perfect security. There is no such thing as an unhackable system. The purpose of your security should be to make the cost of obtaining the resource far greater than the value of the resource itself.
Bottom Line
As a smart developer, you need to assume that the attackers will exploit your client application every which way. You need to assume that they will eventually gain access to your client's source code, and even understand how it communicates with your server. And on the server-side, you need to assume that every request coming from a client is an attack, and treat it as such. This will put you in the right state of mind to code defensively.
What you need to beef up on is server-side security, and that is not trivial by any means. But if you just remember to keep all sensitive code and data on the server, and access it defensively on the client-side, you'll do more to protect your app than any obfuscator can offer you. HTH and happy coding.
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 :)
We're working on a fairly enterprise-y app right now, and the mandate has been that all data be encrypted on the local disk. Currently, the way to do this is to use the username/password entered on login to build the encryption key. Those values are always kept in memory, so it would be reasonably difficult for somebody to hack that (not impossible, but difficult).
Now the app needs to use SSO to log in. Depending on the provider, the implementations will differ, but lets say we can imagine some unique value being generated either by our server, or using the values available from the AccountManager, or something more exotic. However its done, we need a way to build the encryption key from source values that aren't kept on disk. As mentioned above, those are currently username/password, and for SSO, would be presumably something generated in another fashion.
If we were always online, we could rely on the server to keep that value in a database and return it on login. However, this app should also be able to function offline (after you've done your initial login, of course).
Any thoughts? I had explored just encrypting the whole disk, but we can't really enforce users doing that, and if there's a good chunk of data already, it'll take a long time.
Is there a way to keep these values somewhere in the OS that's not easily readable, even with root? For example, if we had a lock screen, is there some way to use the lock screen password to hold encrypted data? Its my understanding that that's the method used for the disk encryption, and there's something similar on iOS. I've read in a number of places that a 4 digit code isn't not incredibly secure, but it would be pretty good, and much better than what we have now.
Any other thoughts? I feel like I'm missing something obvious.
Thanks in advance.
What would be the best most secure way to handle confidential text in an Android app?
The basic structure is (text/int) and some similar variations of it.
The app only shows a selection of the (readable text /readable int) at a time, so decryption will only be done for very few pairs at a time.
I need to make sure that extracting the complete (text/int) information is practically impossible - if possible :-)
Is there any standard library/scheme to handle this?
Many thanks
EDIT (after getting some very interesting responses to this question):
It seems that even when the data is encrypted one could easily take the de-compiled code from the app, combine this with a self-written extraction routine, and hereby get all the decrypted info to a file. Since the encryption key has to be provided to users of the app, everybody could potentially get to the data this way.
So in summary there is no real good solution?
You can save your text/int pair into the SharedPreference.
Because it's not secure, you can encryt the data before saving it into the SharedPreference in the same way as Google do in the Application Licensing package.
More details can be found in the Implementing an Obfuscator part.
The code source of the AESObfuscator can be found in the SDK in the market_licensing/library/src/com/android/vending/licensing folder.
I think in your application you can use a symmetric cryptography and you can store your key in the Keystore. This key should be protected with password. Every time, when you run your application, it will ask the user for the password. If the password is correct then the key is extracted from the Keystore and used to decrypt your data. In this case, there is no difference where you store your data (text/int pairs) because all data will be encrypted. For Android SDK look at the package java.security and to the class java.security.KeyStore
If you want to supply your application with the data that you don't want to be extracted then obfuscation is a possible solution if you write in Java. If you want this functionality to be written in C/C++ then use Android NDK.