2

My web application is a long sequence of games, which submit progress results back to the server via a web API. These progress messages are how we know how many points the user has earned. The points are used to show rankings and status and that kind of thing.

By checking stats, we just discovered that a registered user had earned 90,000 points in an hour or so, becoming the global #1 player, when it should take many, many months to earn that many points through actual game play.

It appears that this user did some kind of observation of the "game complete" message between our game client and server and then wrote some kind of script to send similar messages for many games, tricking the server into awarding points for completing those games.

Each such message includes a checksum of the arguments, which is authenticated on the server, so we think this person must also have discovered the hashing function in our minified and obfuscated javascript code so that they could spoof this as well.

Measures we do or could do

The arguments checksum trick.

The app already requires a login, but this person was logged in. We cancelled the account, but they could just make another.

We could throttle the messages, but no matter what the rate limit is, they could still send messages just below that rate, and run up a huge sticker count illegitimately; it would just take longer. And if the throttle is too aggressive, it would block legitimate progress messages.

We could maybe associate a random GUID with each game, which we authenticate, so that a message that works for one game would not work for another, but we'd have to embed those GUIDs in the code somewhere so each game could legitimately send the message, and then the hack would be harder, but still possible.

Basically, the legitimate message sending code lives on the client, so anything we do could in principle be inspected and reverse-engineered.

So how can this kind of exploit be prevented?

8
  • 1
    Redesign your web app so you are not relying on client-side JavaScript to perform sensitive integrity-related tasks (e.g., the hashing you mention).
    – hft
    Commented Feb 10, 2021 at 21:53
  • What type of game is it? Platformer, FPS, flappy bird clone? I've got experience with developing and combating game cheats but it's much easier to write a helpful answer if I can make my examples applicable to your use-case.
    – Polynomial
    Commented Feb 10, 2021 at 21:54
  • @hft: Agreed, but the client is the only place that knows that, for example, a game was completed. How can the client relay that result back to the server without relying on the client performing the task? Commented Feb 10, 2021 at 21:55
  • @Polynomial: it's actually many different kinds of games, but the general idea is that there's a game that you play and either you just have to complete the game and it sends a message saying so: (playerId = 456, gameId = 123, completed = true) or maybe there are 10 tasks and the message is (playerId = 456, gameId = 123, totalQuestions = 10, correctAnswers = 9). There are about 250 games, divided into families, and each family has a basically similar kind of progress message, with some variation across families. Commented Feb 10, 2021 at 22:00
  • @JoshuaFrank Can you elaborate a bit more than that? The "totalQuestions" variable implies some kind of quiz. I need to know a bit more than "a game you play and you have to complete it" in order to give you some examples of how you can move to a more server-authoritative model without sacrificing UX. You mention "many different types of games" - is there a common thread to the games? Are we talking something like Boardgame Arena? Some sort of quiz site? A bunch of story-driven RPGs? The details help a lot with writing a helpful answer.
    – Polynomial
    Commented Feb 10, 2021 at 22:05

3 Answers 3

4

If the security controls exist only on the client, you have no control over the security controls. That's an intractable problem that appears in all corners of security. If your security model presupposes that a device that the user owns will not be manipulated, then your security model is based upon an incorrect assumption.

You've mentioned a few approaches to making it more difficult, but none of them offer concrete protection because your game logic is completely in the control of a malicious user. This comes up in game cheating all the time, and the only concrete solution is a server authoritative model. In absolute terms, this means running the game logic on the server, not the client.

A fully server-authoritative system is not always feasible. Consider, for example, a first-person shooter game. If the server was responsible for the entire game, including rendering the images that the user sees, it would be unplayable due to latency issues. The first obvious concession is that the game must be rendered on the client-side, but this already opens up avenues for exploitation, such as wallhacking. The work involved with developing a secure game model lies primarily in coming up with a reasonable compromise between user experience, development cost, and security. What you'll likely arrive at is a combination of concrete controls, and compensating controls. The concrete controls enforce certain behaviours and capabilities absolutely, and the compensating controls make it harder to exploit the gaps in between.

You mentioned questions in one of your comments. This type of game mechanic is much more easily adaptable into a server-authoritative model. The game asks the server for a question, the player answers the question, and the answer is sent back to the server for verification. The answer never leaves the server, and the server has authority over whether or not the question was answered correctly, which makes it much harder to abuse. You can apply reasonable time limits on how long a user can take to answer the question, as well as rate limits to prevent obvious automation.

In games where the player moves about a space, e.g. a platformer or RPG, you can enforce that the game cannot progress beyond a certain stage without reaching certain milestones. The server can reject a game completion request if the client has not sent the prerequisite milestone notifications, and minimum timings can be enforced between each notification.

In more interactive game designs (e.g. MMOs or FPS) the server keeps track of player positions in realtime, and rejects actions that are not possible, such as changing position too quickly (speedhacking), interacting with an object that is too far away, or using currency or items that the player is not in possession of.

For turn-based games, such as chess or backgammon, it is possible to perform post-hoc validation of the game at its conclusion. This can be done even if the "AI" player's moves are computed on the client. The game client handles all of the game logic, but must record all of the player's moves and the ending state. If the AI's behaviour must appear to be random in some way, the server is responsible for sending a random seed to the client at the start of the game, which seeds a deterministic pseudorandom number generator. When the game is finished, the client sends the list of player moves and ending game state back to the server. The server then re-plays the entire game through and checks that each player move was valid and that the server arrives at the same ending state as the client provided. Since the same PRNG seed is used on both the client and server, the AI will make the same moves in both play-throughs. If the ending state fulfils the win condition for the game, and the moves/state were all correct, then the win is accepted.

More generic advice:

  • Ensure that a completion notification is tied to a new game notification, and that the time between those requests is neither too short or too long. New game notifications should contain all the relevant parameters for that game (game type, difficulty level, etc.) and server-authoritiative parameters (e.g. the AI seed) should be tracked.
  • Require that games with stages include stage completion notifications. Implement time restrictions on these.
  • Where possible, make random decisions on the server rather than on the client. For example, if a player gets a random prize, decide that prize on the server rather than the client.
  • Where you have deterministic games, get the client to record the sequence of moves and send them to the server. Hash the results and store this alongside the user profile. If the user then makes the exact same set of moves again over and over, the hashes will match up and you can identify that they are automating the game.
  • Analyse your player behaviours, based on logs, and come up with a reasonable upper bound for the rate at which games are completed and scores are increased. Set up alerts when users exceed this bound. If you ban cheaters quickly, they're less likely to come back and less likely to form communities that make your life difficult.
2

We could maybe _, and then the hack would be harder, but still possible.

Yup, that sounds right!

I've never worked in the field of video game anti-cheating, but I understand that it's a full academic field unto itself that comes down to a bag of obfuscation and "security by obscurity" tricks to make the game client hard to reverse-engineer.

If this issue was due to a user reverse-engineering your network messages, then a relatively simple extra layer would be to use TLS between your client and your server, and "pin" the server's TLS certificate in the client (not in a config file where a user could replace it, but actually embedded in the compiled executable). That will make in near impossible for the user to observe and reverse-engineer the network traffic.

I assume your game client is an installed application and not a browser. If it's a browser game then what I suggest won't work due to browser's "Edit and Resend" functionality that works before the browser's TLS layer.

I general though, I think you're into the world of cheating-detection, so I would search something like "video game cheating detection" on Google Scholar`, and get comfy in your favourite chair.

0

It makes it hard to help because you say your games are so diverse in design.

Adding an extra layer of TLS is not going to help because the attacker has full access to the DOM and can simply wait until your handshake completes before manipulating values.

In the end, there has to be some randomly generated secret the server knows that can only be found by playing the game/puzzle.... like a form of captcha.

Working this kind of model into every game will be difficult. If you could describe the games in more details maybe we could come up with a solution.

Quizzes are easy, only server knows the answer. But for more advanced things like physics games this can be especially difficult.

Lets say you have a game like Angry Birds and they need to hit certain targets. The server would have to generate potential angles that could be used, and the game client would have to send back these angles to see if they fit within your correct definitions.

There could be some fuzzy logic here, and it doesn't have to be perfect, but every game should have some kind of turing test built into it. And then of course the values would be signed by your public key and sent back to the server for validation.

There would need to be some throttling here, but the more complex the test the easier it is to throttle.

It will be tricky, but honestly there are a lot of people who find fighting off the bots fun and exciting because it will always be a cat and mouse game depending on the rewards your offering and the determination of the hacker.

If you post specifics of each game I could try and give you more ideas.

Good luck!

1
  • This is a compelling idea. Let me give some thought to how that might work. I don't think there's a problem sharing the details of the games, but there are many and it would be a fair amount of work to analyze all of them. Maybe I could post a few examples, to give some idea. Commented Feb 11, 2021 at 2:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .