A few days ago one person decompiled my app and show me an issue in my source code. I was hardcoding the links and the password of my server in source code of the app, I didn't know through decompiling anyone can see my source code. I use proguard but proguard doesn't obfuscate strings. This left me wondering how is the right way to do this? How can my app make api calls and the server can authenticate it? I did a research but I did't see much content talking about this. My app doesn't manage users and passwords. The user and password that I store in my code are the ones to login in the server.
Yes, it is pretty easy to see decompiled Java code to get keys and the like.
There are a few things to do:
Ensure the "application keys" or "tokens" are not a secret with deep admin privileges. Many SaaS / API Providers give you multiple keys. One is a client key that is limited in privileges/actions that can be performed, and a server key that has more privileges but won't be leaked out via client code. In you case, you shouldn't share the same server login/admin passwords. Leverage Principle of least privilege (https://en.wikipedia.org/wiki/Principle_of_least_privilege)
Ensure the string is a static final. In this case, Compiler and Proguard which allow string inlining. This makes it a little harder to know what the string is for. If you have a single "Config" class, it's pretty easy to search for 'facebook' in facebookAppId, 'secret' googleSecret, etc.
To be really secure, you can perform some encryption, or other algorithm on the string, but this means you also store the encryption secret in the code itself also.
In general, I believe (1) gives the most since you should always assume any string in client can be found/hacked, whether Android/Java with Proguard or minified javascript.
Related
I am using SQLCipher for Android. I have done all the necessary things that are needed for
loading the libs as mentioned in http://sqlcipher.net/sqlcipher-for-android/
I observed that you set the password i.e the key in :
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);
Then how is your password safe from a hacker? As it can be accessed from a java file. ?
Is there any correct way where i can store the password ?
Thanks,
Nibs
Then how is your password safe from a hacker?
It's not. Hard-coding a passphrase makes for simple demonstrations, though.
Is there any correct way where i can store the password ?
The user should supply the passphrase for the user's database via your UI. The user then stores the passphrase in the user's head, or perhaps you combine what's in the user's head with something else for lightweight two-factor authentication (e.g., MAC address of paired Bluetooth wearable).
I would like to suggest the following approach:
The first time you create the database you have to create a random password.
You store this password in the Keystore.
Whenever you open the app you read the password from the keystore and use it for connecting to the database.
So how does the keystore access work? See blog entry 1 and blog entry 2 and the corresponding github repository. The solution is available for Android version 2.1 to 4.3.
Big caveats:
The solution works only with private API access, so it might break in the future.
A screen lock password is required to store keys and all keys are wiped if a user removes his lock screen password.
What is being overlooked is the fact that the demonstration given by SQLCipher is purely for demonstration . It is up to the imagination of the developer to overcome the obvious. Slightly less obvious is that you would NOT store the key in a private local variable, since performing a strings search against your class files could reveal your key, reducing the dictionary necessary in a successful brute force attack. Open your classes.dex in a hex editor and try it.
It isn't the .java files you should be concerned with, as only your developers should be in there. It's the .class files. The next level of effort is some effort of obfuscation, but that really only limits the impatient.
Take a look at this discussion
https://groups.google.com/forum/#!topic/sqlcipher/OkE0rUwXEb8
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.
The comment for the class BillingService recommends that:
You should modify and obfuscate this code before using it.
OK, but what must be modified?
The class name? The TAG used for logging? Method names and data members? The logic and program flow itself? Other?
In other words, I can understand the need for obfuscation, but how can I get away with implementing the recommendation without rewriting everything from scratch (potentially with bugs that are worse than not modifying anything)?
I'm working on this at this moment and my approach, so far, is as follows:
I'm using the BillingReceiver, Billing Service, PurchaseObserver and ResponseHandler.
I've moved all the Constants into my own Constants class and all the above classes are included in my own package.
I've done away with the PurchaseDatabase class and integrated parts of it into my own SQLite database, DBAdapter and data access classes.
I've changed the CatalogEntry into my own model object and my UI will be quite different to the example e.g. RadioButton group rather than Spinner for product items (I only have 4).
It says in the Security class 'For a secure implementation, all of this code should be implemented on a server that communicates with the application'. I'm 'fortunate' that my app has to contact my server anyway so I'll be implementing these security measures on the server and I'll be doing my own validation of the purchase info passed to the server. I'm looking to secure this part of the comms using SSL and I already require a prior username/password (hashed and salted) which is stored on my server.
I'm cutting out any other superfluous code which I'm not using e.g. payload editing.
Some of the methods have 5 or 6 parameters in their signature e.g. onPurchasestateChanged() - I was thinking about combining these into a single wrapper object (but haven't done so yet).
I'm testing it slowly and thoroughly, so that I understand what's going on, and following the recommendations. I used the complete sample at first to make sure it worked and tested the static responses. Then I started making my own changes while still doing static testing. I'm still testing with static responses and I will follow the flow of messages to understand the interchanges going on. Once I'm happy with this I'll test with my own product Id's and try and satisfy myself on the data and its security.
I've thought that the developerPayload string could also be signed and encypted and when returned to my server, decrypted and checked for integrity.
Finally, I'll obfuscate the code using ProGuard and follow some of the tips for doing so which are available on StackOverflow.
Hope this helps.
No good news here: You need to change anything you can, in addition to using Proguard. This includes merging classes, splitting them, moving certain methods from one module to another, and especially encrypting the purchase information stored into the database, as the description for the PurchaseDatabase class suggests:
You should use an obfuscator before storing any information to
persistent storage. The obfuscator should use a key that is specific
to the device and/or user. Otherwise an attacker could copy a database
full of valid purchases and distribute it to others.
The reason is that with tools like AntiLVL it is very easy to compare your decompiled (obfuscated!) code to the original sample and deduct from it whatever needed to compromise it. It is impossible to completely prevent cracking, but you should try to make it as difficult as possible.
They explain it as follows:
The in-app billing sample application is publicly distributed and can
be downloaded by anyone, which means it is relatively easy for an
attacker to reverse engineer your application if you use the sample
code exactly as it is published. The sample application is intended to
be used only as an example. If you use any part of the sample
application, you must modify it before you publish it or release it as
part of a production application.
In particular, attackers look for known entry points and exit points
in an application, so it is important that you modify these parts of
your code that are identical to the sample application.
It means don't use the code as provided, change some part of it so that hackers won't be able to know what code you use.
Basically, I don't think they meant the billingService itself, but the way you use it in your application.
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.