5

This question already has an answer here:

I am developing an offline web app (game) for android using cordova (phonegap). The leaderboard of the same is maintained online in my server.

Currently this is how the leaderboard is updated

Step 1) The user's score is stored in the offline app's local storage.

Step 2) The user presses the "update my score" button connecting to the internet.

Step 3) The button basically sends an ajax request to https://mywebsite.com/scoreupdate.php?userid=user_id&score=obtained_score

Step 4) Based on this the database is updated in my server by scoreupdate.php file and returns success.

These are the problems I am facing

1) Anyone can easily visit https://mywebsite.com/scoreupdate.php?userid=user_id&score=obtained_score if they know the user id (It can be easily obtained from the app's localstorage data) and he/she can update his/her score in the leaderboard simply by replacing obtained_score value with some high value to get a better position in leaderboard.

2) Any secret value stored in the app or localstorage can be obtained easily as the whole thing is built in javascript. Reverse engineering of the app is also possible so I couldn't find a way to efficiently authenticate that it is the real app which is sending the request to the server and not a person.

My requirements

1) The app must be able to authenticate the scoreupdate.php file that it is the real app and not a person. So that only the app will be able to update the leaderboard.

2) The logic of the authentication shall not be cracked by the user just by reading the source code of the app. (eg: multiplying the user id with some numbers and doing the reverse process in server won't work)

Is there some way to accomplish this?

Javascript scrambling is not effective as it can be de-scrambled easily

EDIT

I am not worried if someone steals the user credentials via a MITM or any bruteforce like attacks. Even the real user who owns the profile should not be able to update his/her own score.

marked as duplicate by Neil Smithline, Rory Alsop Jan 1 '16 at 0:52

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    No. You'll have to settle for much less. – Neil Smithline Dec 31 '15 at 18:11
  • 1
    @NeilSmithline Isn't this possible? – Sandeep Thedarkprince C Dec 31 '15 at 18:12
  • 2
    It's just not possible. You could add authentication so users could only update their score instead of anyone's, but as far as preventing them from cheating it isn't possible as you don't control the device they're running the game on. – André Borie Dec 31 '15 at 18:27
  • 2
    Google offers some high score functionality on Android platforms. Have you looked at what they have? They may be able to do better as, in unrooted phones, they own the OS. They'll be no hope for rooted phones. But using them may be good enough. Let them worry about forgeries and such. – Neil Smithline Dec 31 '15 at 20:16
  • 2
    No. You can't prevent cheating, though you can discourage it by obfuscation, signing data, and etc... It always comes down to there being no security without physical security. You don't have physical control of the mobile device so you're out of luck. – Neil Smithline Jan 1 '16 at 6:35
7

I disagree that it is impossible.

Depending on the form of your game it might be possible to apply the following scheme:

  1. During the game, record the starting state, including seeds to RNGs and all inputs from the user.
  2. When submitting the game, submit this "replay" of the session to the server together with the claimed score.
  3. On the server, run through the game logic with the provided input and see if it results in the same score. If it does, the replay is valid and you update the score.

This way, you have effectively transformed the problem of cheating to the problem of writing a bot or a solver for your game which is the best you can ever get in a situation like this.

Basically this is a very good solution for any games that can be viewed as an NP-complete problem where verifying a solution is computationally easy while finding it is computationally hard. One such example is Sokoban.

  • 1
    You really not preventing cheating, just making it more difficult. So your first sentence is wrong. – Neil Smithline Jan 1 '16 at 6:38
  • 1
    That is a nice way. But sending the whole log to the server is tedious. I appreciate the answer and will use this method if I couldn't find any better solution. Thanks a lot. – Sandeep Thedarkprince C Jan 1 '16 at 6:54
  • 1
    @ZetaTwo - ok. That makes sense. I did actually miss the "depending on the form of your game". I agree that if the game is of that type, then this would work. I wouldn't assume that some random game happens to fit that criteria. Perhaps OP can let us know what the game actually is... – TTT Jan 2 '16 at 2:09
  • 1
    As a side note, I undid my DV, and I'm tempted to remove my comment about "fooling everyone", but I'm going to leave it for continuity of the comments. – TTT Jan 2 '16 at 2:25
  • 1
    I think this is a valid solution that would largely prevent cheating. True, a very determined and skilled cheater could come up with convincing statistics / video to cheat with, but this would probably deter almost all cheaters. It would be tremendously harder to make a non-obviously cheated replay than to simply falsely report a high score alone. Oftentimes security cannot eliminate risk, but it can greatly reduce it, and I think this does that. I also thought about the game replay along with the high score (I have seen it done before), and was going to post it here. Good idea @Zeta Two. – Jonathan Jan 5 '16 at 17:05
6

No, this is impossible.

You are relying on the client to provide accurate data. But you can not do that, because the client is outside of your control. It runs on the users hardware, which means that the user can change it in any way they want and there is nothing you can do about that. Any attempt to authenticate that the client wasn't modified must also run on the client machine, which means it isn't protected against manipulation either.

The only way to prevent players from cheating is by running all game mechanics on your own server.

3

With an offline application this can't be achieved because it forces you to trust the application (which can be altered) to store and update the score. There is no way around this for an offline application.

Even with fully homomorphic encryption the offline application would be able to tamper with data even if it can't see the original data.

If the client application is responsible for score-keeping you can only hope for honesty and frustrate cheating attempts via obfuscation; you can't actually prevent them.

A possible incomplete solution that can address a high proportion of cheating is using tuned bayesian nets to perform fraud detection. You evaluate changes in game play activity and score changes into low, medium, and high buckets and then use a bayesian net to fuse the results into a single risk score. That is pretty sophisticated and far from foolproof, but may be an option if the app must be offline.

If you can make it an online application instead you can move rule management and score-keeping to the server which is in your control where you can prevent cheating. Even then it is still a tricky process if the client is able to send anything more than user input events.

  • 1
    You lost me with the bayesian net. What would stop the fraudster from just continually sending slightly better scores that fit within the bounds of the net? – TTT Dec 31 '15 at 20:07
  • 1
    @TTT that's where the net would have to be extremely sophisticated. It would also be hard not to cause false positives where genuinely expert or eclectic gamers would be caught by accident. You need a lot of typical gamer data to generate worthwhile nets for this. I just wasn't comfortable saying outright no here since it prevents you from deploying you app offline. – Alain O'Dea Dec 31 '15 at 20:31
  • 2
    So in other words, it wouldn't work well enough to bother... You just wanted to let the OP down easy? You're too nice. :D – TTT Jan 1 '16 at 0:03
  • 1
    @TTT it can work. It does work extremely well for us at work, but it takes years of tuning ;) – Alain O'Dea Jan 1 '16 at 0:26
  • 1
    My definition of "working" is 100% accuracy (for this scenario of preventing cheating). If you need to tune your fraud detection algorithm over time (and perhaps continuously beyond that), I don't think it is a viable solution for this particular problem. – TTT Jan 1 '16 at 16:17
1

Sorry, no can do.

In general, if your requirements are:

  1. Have an offline client.
  2. Make the client code open source or easily decompilable.
  3. Prevent the client from cheating.

Then, Choose any 2 of those.

Note: even if you decide to change #2 and go with compiled code that isn't easily decompilable, you are still at the mercy of security by obscurity. You can hard code encryption keys and hope that no one ever figures it out, and if your game is just for fun that may be good enough, but if money is involved it may not be.

The best option of the 3 to change is to not have an offline client.

Caveat: above I said "in general" because there are specific types of games where you can accomplish all 3 requirements, for example games that are intrinsically hard to solve (e.g. imagine a Rubik's Cube type game where the solution isn't widely known yet). See Zeta Two's answer for more information about these types of questions.

  • As I stated in an above comment, while this is usually the case, it is not true in general. Perfect example: Sokoban. – Zeta Two Jan 2 '16 at 0:36
  • Agreed. I've updated my answer. Thanks for pointing that out! – TTT Jan 2 '16 at 2:21
0

The only real way to solve this is with custom hardware where the cryptographic keys and the source code are embedded in a device in a way that is very difficult for normal users to extract or modify.

For example, you could have a video game system where it reads games off of encrypted DVDs. The video game system (running secret source code existing in read-only memory on the system) can decrypt the video game (using a secret key embedded on the device) and verify it came from a legitimate source and wasn't modified. Inside the video game source code (that your system verified wasn't modified and can't be leaked), you can include a private key that is used to digitally sign combinations of username and high scores when submitting scores to the online leaderboard.

However, once you allow users to view and modify the source code, you've lost (as the user can just modify the source to change the high score to any value right before the time the score is normally submitted), unless there is a way for the user to also submit their moves and have the server verify those moves correspond with the score.

For example, if the game involves solving puzzles in X moves or less, and you want to submit that you solved the N-th puzzle, you could have your game submit the series of moves you made, and then your server can check that those moves consist of a solution that solves the N-th puzzle in X moves or less and that it was submitted at the time given by the server's clock.

  • Sorry for the DV but I believe most of your answer is incorrect: The OP states the client is written in JavaScript, so as it stands you can't hide the code.as you suggest. Then you say "the only real way to solve this" is by re-writing the code with something that can hide the keys. But the other way to solve this (and likely the better way) is to not have an offline client. Also, your last paragraph suggests using the server's clock as some sort of validation, but with an offline client where answers are submitted later, those times can be manipulated to anything. – TTT Dec 31 '15 at 23:28
  • I think your answer may be salvageable though as your middle two paragraphs seem to be an interesting idea if you want to attempt to "secure the source code". (See the note in my answer.) – TTT Dec 31 '15 at 23:38
  • @TTT - First, about server time vs client time, reread what I wrote -- we are in agreement. I never said anything about trusting a client submitted time. I said you only trust the time that it was submitted as given by the server's clock and then validated server-side to work to produce a given score. I never said anything about looking at a client's time or the client submitting a time. E.g., a puzzle was released at noon and your leaderboard consists of the first people who submitted valid solutions with the times received by the server. – dr jimbob Jan 1 '16 at 1:05
  • Second, I agree this won't work for a mobile game with completely open source code that you can run on untrusted hardware. But I think it's worthwhile to say that while difficult this problem can be solved on trusted hardware that only runs trusted unmodified software (and this is how online high scores work for video games running on xbox, playstation, etc). And nothing in the question prevents this -- someone could design hardware devices that run a modified android that only runs signed javascript applications and digitally signs submitted scores. – dr jimbob Jan 1 '16 at 1:08
  • Regarding your first comment - your idea assumes that the client communicates with the server to get a puzzle when the user beings the game. Maybe that's how it could work, but then I wouldn't call that "offline". I was assuming that the client is always offline, except to submit a high score. – TTT Jan 1 '16 at 16:06

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