From this. We can't prevent reversing engineer.
But how do we detect if app have modified and trying to access our server?
Especially in iOS and Android.
Something we have used with success for a while now is the following :
During the compile phase, make MD5's of the DLL's & Executable and save them to a place the server can access.
Before the client connects to the server, have it compute the MD5's as well
OnConnect, send the MD5's to the server and have the server validate them
Since the correct MD5's should be a secret to the server, you will catch early attempts made to modify the code, and flag those accounts for further review. But even then an above-amature level dev will figure this out and just send the MD5's you are expecting.
It's not fool proof, but i honestly believe nothing is, all you can do is complicate it as much as possible, this does complicate things a little bit since the MD5's will change every time you publish an update, you could even hash the MD5 with the connectionID, which would make each connection's hash it sends to the server unique.
Using this approach will make it impossible to disabled/remove the checks, because the server always expects an MD5/Hash to be sent.
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead("path-to-your.file"))
{
return md5.ComputeHash(stream); // returns the MD5 byte[]
}
}
As the post you linked to said very well :
You basically can't protect your application from being modified. And any protection you put in there can be disabled/removed, You can do different tricks to make hacking harder though.
I've closed this question. But I've an idea. Hope some of you consider and comment about this.
As the answer said.
You basically can't protect your application from being modified. And any protection you put in there can be disabled/removed, You can do different tricks to make hacking harder though.
Any protection in client can be removed.
How about
Put the verification code on server.
Download this code and run it at runtime. (each run must expect unique result)
Send verification result to server for authorise it.
Because you have download a part of script. you have to download DLL from server side or alternative use this
Related
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 just can't get my head straight about this one. I'm currently building a rather large-scale application on Android. I've run in to a couple of problems regarding security and authentication though...
The Scenario:
I have an application that's making calls through HTTP (will implement SSL later) to a server running PHP and MySQL. Of course i want to use the existing user-database, so migration to another DB is not a solution..
I've managed to create the "register users via Android to the server"-functionality.
I've also made a working login, BUT this is where the problems start.
As users in the Android application I'am working on adds, edits, deletes and sync stuff on the server via/to the application, things get rather complicated. A little too complicated for me it seems :)
Problems:
As I get the result from my server-side login and pass it from the
server to Android via JSON, the connection dies and server-side I
'aint logged-on (sessions dies) whereas on the phone I'am. How can I
make the log-on persistent both on the server and in Android without
the need to log-on again? So that subsequent calls from Android to
the server is made with the same user, still authenticated. I.e. I
want sort of a one-time login ('till I logout) like in the
Spotify-app (and many others).
If I've understood things right, implementing SSL correct makes it
possible to send passwords in clear text to the server without the need to hash them first. Is this correct?
I just can't stop thinking about the fact that a MIM-attack would compromise any unique id I send from Android to the server. My first thought was to have the UID on the Android device as a "key" to the server after a successful log-on. But if that key gets in the wrong hands, the user associated with that UID will be compromised. I've looked at the AccountManager on Android but it seems rather over-kill in my case.
If someone could supply examples or at least guidelines, I'd be much grateful!
Thanks in advace!
ADDED SOLUTION DIAGRAM AFTER EDIT
Notice that this diagram shows the first start of the application. Later startups will NOT show the Login / Register form, but use the DUT instead.
// Alexander
Issue some form of a short-lived authentication token to Android apps. They would need to pass it in every request, and you will check it your Web app. Breaking the connection doesn't end the session, if it does, you have bug in your Web app: fix it. In Android, as long as you are using the same HttpClient instance, it will continue to use the same session, nothing special is needed.
Whatever you do, do not put off implementing SSL, do it now.
I'm devepling and android application that should connect to an application server.
What I'm asking about is, should I write the url of this application server statically inside the code or is there a way provided by android to dynamically change the url if needed ??
Taking into consideration that once the app is uploaded on play store, the application server should reserve the address and never change so as not to affect the android app.
I'm just asking about best practices in those situations.
Thanks all :)
Although that would be nice, it might not be worth the hassle. I think it's fine to code in the URLs as they are currently. If for some reason you change the endpoint, try and make it so you send an error saying that the user needs to update the app (and release a new version with the updated URLs). It's also a nice way of indirectly getting your users to update to the latest version so you don't have many to maintain!
Also, if your server moves, it's still not a problem, since you'll still be using the same domain name to point to your server!
(This is assuming that it's still the same domain name, and it's just the endpoint changing, and you don't need to reuse the previous endpoint for something else. Yeah, quite a few assumptions :) )
It is best to consider that your server will be relocated in the future, because you never know. Unless you are willing to upgrade your application anytime it happens, dynamic configuration is the best approach.
You can write the URL of the redirect server in the code, and have that server redirect to different URLs as required. The redirect "server" in its simplest form can be just a text file stored on your company's website, for example.
I'm wanting to create an android app that gathers information and then uploads to a server -- however I don't want people to be able to edit the file before it's sent to the server. I can do the first part of it, but am unable to do the second part. Can anyone tell me the best way to go about this? I don't mind if the user knows what's in the file, just don't want them editing it and then uploading their edited information to the server.
You're pretty much out of luck since the application is run by the user and the output is controlled by the user. The only way you could take over user's system so he would have no control over it would be using trusted computing with all of the ethical and philosophical implications - see eg. Can You Trust Your Computer? by Richard Stallman. The only thing you can hope for is having a secure connection between your server and user's systems (SSL/TLS) but this is still user's system over which you have no control.
The only correct answer here is Zed's.
The rest of the answers rely on Security through obscurity.
The bottom line is: if device is not totally locked down (= trusted computing) then users can reverse-engineer the application/file-format/network-protocol and submit false data.
Fact of life: people with huge resources (media industry, IT industry) have tried to pull this off (DVD, BluRay, game consoles, etc..) but eventually talented engineers on minimum budget have been able to break this protection schemes.
So, it might work, but only if data is not important and nobody bothers to break it.
There are a couple of approaches you could use here:
Encrypt the file before its saved to the device, the user will be unable to read/modify it.
Encrypt the connection to the server, SSL can protect against a 3rd party interfering with it.
Don't save the file in a public location, place it inside your app's private data directory. The user will be unable to access it.
Depending on how sensitive this information is going to determine which combination of methods to use.
Well as for Android you cannot prevent people from accessing files on the public filesystem.
Maybe there are better ways to handle this but I would simply crypt and decrypt the data before submitting and by using a passphrase or some sort of parity check one could validate the data.
Some rough ideas:
You could view the information that is being sent to the server to the user and then ZIP the file that's being sent with a password beforehand so the user doesn't get a chance to edit it:
Write a password protected Zip file in Java
Of course, you'll have to make sure the user doesn't know the password ...
Or you could build a checksum of the text that's sent and validate the checksum on the server. Here, again, you have to make sure the user doesn't know how the checksum is built and change it accordingly.
Or you could not safe the information to a file at all but into the app's database or private filespace (where non-root-users can't access it).
Whether it's the pasword or the checksum, you could send that information to your server with a normal HTTP-request so it won't be "visible" to the user (followed by a second request that actually sends the file), but if we're talking about users that know how to handle network-sniffers on their phone (needs root, AFAIK), you'll have bad luck, it's their device and their data that's trying to leave it after all :)You could try to use a secure connection to fix this.
What you could do :
Sign the file with your application
Check the signature on the server, check if the certificate is a certificate that is authorized
This will help a bit, but you'll still have the private key bundled with your application... someone may be able to find it and then sign modified files...
Another idea : can you compute the data or is it user generated ? If it's computed why not just compute the data and send it to the server (over SSL) without even writing it to the filesystem ?