I look forward to develop an Android / iPhone application, those will be using a private API (Non-Free) with embedded client-key.
Now, since it is possible to reverse-engineer application binaries and scrap out strings. I am worried of losing my client-key and there by exposing the private API to the attacker.
How to manage this ? Can you provide links to articles discussing such situations ?
Considering I have development access to the private API, what mechanism can I built in to that to preserve the privacy of the whole system.
It will always be possible to use the private API if you have access to your applications code (see this thread as well). You can make it harder, though. And you can restrict the use of the API with the following options
1) if it's not "your" API, don't put the key into the app but into a server you are running to serve as proxy for the foreign service (you probably still want another key for your server to go into the app then)
2) encrypt/scramble the key so it is not grabbed easily:
simple example for scrambling: put the key into a file; generate a random file of same length; xor the key file with the random file (and write it to disk again); whenever you need the key read both files and xor them again (any reversable operation instead of xor will do - more complex operation, spread over your code will make it harder for the reverse engineer)
encrypt your key using a passphrase spread over you app (on deployment android apps are obfuscated anyways, so finding it gets a bit harder)
3) if it's your service or you have a proxy set up, restrict the number of uses per client/IP or offer only parts of the service over your proxy
Note, option 1 may even be required if you have a contract which forbids to make your key public.
Related
I ran a security test via the ImmuniWeb tool on my Android app APK. One of the observations the tool made was that one of the app components uses a predictable random number generator. It further said:
Under certain conditions, this weakness may jeopardize mobile
application data encryption or other protection based on
randomization. For example, if encryption tokens are generated inside
of the application and an attacker can provide the application with a
predictable token to validate and then execute a sensitive activity
within the application or its backend.
Example of insecure code:
Random random = new Random()
Example of secure code:
SecureRandom random = new SecureRandom()
There is 'new Random()' found in file 'kotlinx/coroutines/scheduling/CoroutineScheduler.java'
There is 'new Random()' found in file 'kotlin/random/FallbackThreadLocalRandom$implStorage$1.java'
The app heavily uses Kotlin coroutines so I am not in a position to remove the library. My doubt is how do I avoid this vulnerability? Can I do something about it? Lastly, if this really is a valid risky code, can we report and expect Kotlin to push an update to fix it?
I agree with #Morrison Chang . I don't think the coroutine scheduling code needs to be cryptographically secure either.
That logic isn't doing something like creating initialisation vectors for a block cipher etc. so it ought to be fine...
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.
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'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%.
Currently I am using:
Algorithm_mode_padding="RSA/ECB/PKCS1Padding"
Provider="BC"
I have heard that ECB can cause patterns in the output. What is the most secure Algorithm, mode and padding for Android at the moment? I will be using this for license files.
Also, what is the best keysize to use when creating a new public and private key?
ECB isn't advisable in general, but worrying this much about encryption schemes and key sizes is moot if you're using it (presumably) to decrypt files on your device.
If you're decrypting a licence file in your application in order to verify it, then you would need to have the private key embedded in your application. So no matter what key length it is, the user would be able to access it.
On the other hand, you could retrieve the private key from a server dynamically (or similar), but at that point you may as well just do the decryption/validation all online anyway.