Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I have written an Android game. Now, I want to connect the marks of the players.

The code below is the client side program, which send their names, countries and marks to the server. Basically, I use ':' to separate the information.

However, hackers can know my server ip and port by decompiling .apk file. Then, they can create a basic java application to access my server. They could send me "hacker:badserver:123456789". Finally, the top mark becomes "123456789".

Is it more secure method to connect user's data?

Socket client = new Socket(ip, port);
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hacker:HK:3910");
share|improve this question
add comment

3 Answers

You have encountered two "hard" problems: authentication and authorization. There is plenty of information online on thes topic, but in your case I think your problem goes back to the design of the app.

Let us start with two questions:

  1. How do you know whether user is allowed to post a high score? (Authorization)
  2. How do you know the connection to your server comes from an actual game user and not somebody impersonating the game like in your Java example? (Authentication)

Before you try to re-invent the wheel, be aware that there are many libraries that do just that, with the added benefit of being mature, tested, working and well documented.

Not knowing the details of your app, here are a few suggestions:

  • Let users play in 'solo' mode or in 'online' mode. In the former mode the game is standalone and does not need to make any network connections (good for privacy-aware users). In the latter case users SHALL register with your server.
  • Once a user is registered (login/password) and you have verified they actually are a "real" user to some extent (e-mail responder, text message, etc.), your server can send back a 'token' to play.
  • When the app wants to send its high score to your server it MUST authenticate itself by providing the token in a manner similar to what user @mike-mackintosh described in his answer.
  • All communications to/from should obviously be encrypted with TLS or other forms of strong crypto.
  • Your app should validate the certificates to avoid man-in-the-middle attacks.

The scenario is simplified: of course an attacker with enough resources could register a fake account, reverse engineer your app, determine the message to use and send bogus data to your server. To prevent it you'll need to ask the platform to verify that the app hasn't been tampered with, which in turn means extending the chain of trust to the operating system running the app, and so on. In the end it gets complicated (ever heard of "trusted computing" and digital rights management?) and depends on the value you're trying to protect.

Another avenue of research could be some form of server-side validation. For example, every time a user posts a score higher than X, they must also supply "proof" that they unlocked a certain achievement e.g. a random string that is saved in the user profile when they reach a specific point in the game. In this case you can double-check server-side that the user did actually pass the previous achievements earlier on.

You can spice things up furtner by generating the 'level' tokens by combining the phone's IMEI with a random key and using some form of public key encryption so that each user is tied to their phone. Which would work, unless somebody were using a custom ROM for android that allows tweaking the phone's IMEI, and so on.

share|improve this answer
add comment

You have a few options. Honestly, you would most likely want to enable some sort of authentication, like HMAC to send the requests to make sure they are coming from your application. If you don't know about HMAC, google it, there is a lot of content.

Take a look at this Security.StackExchange answer:

A message authentication code (MAC) is produced from a message and a secret key by a MAC algorithm. An important property of a MAC is that it is impossible¹ to produce the MAC of a message and a secret key without knowing the secret key. A MAC of the same message produced by a different key looks unrelated. Even knowing the MAC of other messages does not help in computing the MAC of a new message.

An HMAC is a MAC which is based on a hash function. The basic idea is to concatenate the key and the message, and hash them together. Since it is impossible, given a cryptographic hash, to find out what it is the hash of, knowing the hash (or even a collection of such hashes) does not make it possible to find the key. The basic idea doesn't quite work out, in part because of length extension attacks, so the actual HMAC construction is a little more complicated. For more information, browse the hmac tag on Cryptography Stack Exchange, especially Why is H(k||x) not a secure MAC construction?, Is H(k||length||x) a secure MAC construction? and HMAC vs MAC functions. There are other ways to define a MAC, for example MAC algorithms based on block ciphers such as CMAC.

Additionally, to protect your source, use proguard, which helps obfuscate the APK source from a dalvik decompile. http://developer.android.com/tools/help/proguard.html

This is not foolproof, but you'll weed out some of the bad eggs quickly.

share|improve this answer
    
In this case the secret is stored on the client correct? –  KDEx Jul 3 at 20:08
    
Yes. You will almost always need something on the client to validate the integrity, such as a pre-shared key, public/private key, client ssl cert, etc. At least the way described, it's hidden in the source and simple reverse engineering won't reveal it so easily. –  Mike Mackintosh Jul 6 at 13:57
    
If the question is concerned about RE to begin with i would say any stored secrets on the client would be less than optimal. Although you are right in that this will increase the effort and may discourage some bad users –  KDEx Jul 6 at 14:03
add comment

There are two things that you should do to solve your issue.

One is look into mutual SSL. This will allow your client to authenticate your server and your server will authenticate your client avoiding repudiation. There are a few links on SE about this.

Mutual SSL provides the same things as SSL, with the addition of authentication and non-repudiation of the client authentication, using digital signatures. When mutual authentication is used the server would request the client to provide a certificate in addition to the server certificate issued to the client.

mutual authentication between two clients

http://stackoverflow.com/questions/23114049/ssl-mutual-authentication-fail-on-android-client-accepts-servers-certificate-but

The second thing that you should make sure you do regardless is to lock down your server's API. Validate all the input that you receive regardless.

Realize that in Android the user gets your apk, so in many cases security efforts can be overcome. However with the above steps you should be able to increase the level of effort so much so that malicious users will not be interested in spending the time to break your app.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.