1

I have spent the better part of 2 weeks looking at a solution to secure my game. It's a game for Android/iOS that has its own server/database.

So far, the only security I have is salt+hash passwords. But anyone can call my API.

So I wanted to change this, one solution I found that is very simple is to hash my query when calling my API using a secret that is stored in both the client and server. Of course this means if someone decompiles my app, they can access my API.

Worst case scenario, they can give themselves free premium version of my game ($4), and increase their own rank (which I would see, and just remove the user). I am okay with that, it would become a problem if they could do it for any user, but that should be impossible.

In my opinion the solution is okay for this threat model, if they want to go through all that trouble just to save $4, I'm okay with that.

Does anyone with more experience see a fault in my approach? If it is good enough, what is a good way to obfuscate the secret in my client?

Reference: Answer by speedplane Here

Green_qaue
  • 155
  • 5
  • Trying to keep secrets on a client that you are shipping out is a losing battle. Instead, are there APIs you can hook into on Android/iOS that are linked to the purchaser's account? For example, on Android there are [Play Games](https://developers.google.com/games/services/android/quickstart) APIs, which provide leaderboards, multiplayer arrangement etc. You might be able to use something from this API as an identifier for your own service, which your server could use to verify that the user is an actual Google Play user who bought your app, etc. - or just use the leaderboard from that API. – cloudfeet Mar 21 '17 at 13:26
  • @cloudfeet Google Play API require you to use Google-accounts. Which I don't want to do. – Green_qaue Mar 21 '17 at 13:36
  • 1
    What app store are they using to purchase your app at the moment? Whatever it is: even if that app store doesn't have some gaming API, they might provide some way to get an identifier for the current user, which you can validate against their servers to make sure they're valid. – cloudfeet Mar 21 '17 at 17:24
  • @cloudfeet Note that for Android apps, they don't necessarily have to be distributed through an app store. Many Android phones still allow sideloading (which I find it to be very useful even given the potential security concerns). – JAB Mar 21 '17 at 19:05
  • You should at least have unique secret per user. That way if someone do bothers to decompile your app, all they can get is their own secret, not a global secret. Either way, it will not stop someone to create app of their own used to cheat in your game and distribute it online for anyone to use. – Marko Vodopija Mar 21 '17 at 20:56
  • @MarkoVodopija I do use an per-user secret. So sure someone could make an app to cheat in my game. But for anyone to use it they would have to decompile their app. And honestly how many are going to do that for a silly mobile game. – Green_qaue Mar 21 '17 at 21:01
  • It depends on how popular your game becomes ;) I wish you luck! :) – Marko Vodopija Mar 22 '17 at 06:40
  • @cloudfeet Was just thinking. In LibGdx we always keep a reference to our Game-class (MyGdxGame extends Game). So, why not just send a "key" from the server on game-start, and keep that key in a global variable in our game-class. That way it can always be accessed, but its not actually saved in the client or preferences. – Green_qaue Mar 23 '17 at 08:25

2 Answers2

1

The key to such questions is to have a threat model. In a threat model, you capture what capabilities your threat has and what they want to do. You can then balance it against your costs.

It sounds like you've gone down that path correctly. You've identified that the attacker may be willing to disassemble the code to get a shared secret. You've identified the cost is $4 or the possibility that you have to spend a little work erasing a user account on your server. The balance is up to you.

Consider that, in the case of console game DRM, embedding the secret is all they can do. They have gotten pretty clever about it. A famous case was Spiro the Dragon which had many elements of DRM in it. Some were easy to spot and cracked immediately. Others were more subtle. Some would just set a flag somewhere that would get checked 3 levels later. If the flag was set, the map would have no eggs (an essential item for advancing to the next level).

Spiro was eventually fully cracked. When they finally did so, the crackers actually thanked the dev team for giving them such an interesting challenge. The DRM was considered a complete success. Why? It took more than 2 months for the crackers to finally get all of the cracks in place. For console games, most purchases of the game occur in the first 2 months, so the piracy community failed to negatively impact sales during that key period.

Cort Ammon
  • 9,216
  • 3
  • 26
  • 26
0

For part 1 of your question, I don't know much of the technicalities of android development but a lot of games went online to reduce piracy. If there is an online community (your high scores for example being displayed) then you can ban users from your community that are pirating your stuff. Single player offline games are still very piratable and usually rely on some amount of good faith.

For part 2 of your question, about securing your high scores: https://security.stackexchange.com/a/148430/8072

daniel
  • 774
  • 3
  • 12
  • This does not answer any of my questions: Does anyone with more experience see a fault in my approach? If it is good enough, what is a good way to obfuscate the secret in my client? – Green_qaue Mar 21 '17 at 13:35
  • @Green_qaue - you proposed "salt + hash to protect the API" as a way to protect your high-scores, and then asked whether there are flaws in this approach. As you yourself point out in the question, your scheme has flaws, and the linked answer for part 2 points out some *better* ways to secure your high-score table. – cloudfeet Mar 21 '17 at 17:31
  • @cloudfeet ...but thats not what it says? I said "the only security I have is salt+hash passwords", that doesnt protect the API, that has nothing to do with the API. That is how I store user passwords. I appriciate that you are trying to help it's just not what I asked though. – Green_qaue Mar 21 '17 at 19:13
  • @Green_qaue Sorry for any confusion ("salt" was wrong in my comment). I'm referring to when you said clients would "hash my query when calling my API", and linked to [this answer](http://stackoverflow.com/a/21842679/472388), which describes using hash/MAC as a signature for API calls. Given the game-specific nature of your API, the answer linked in "part 2" above is a stronger protection against bad-faith API calls. – cloudfeet Mar 21 '17 at 21:32