views:

49

answers:

2

In my game/app (iPhone) the client side sends http requests (get or post) to the game http server. Requests have this form:

gameserver.com/userId/givebonus/100

This for example would give the userId a bonus of 100.

Now, we encrypt the server request and it will become something like:

gameserver.com/42c34c234c234/ghjghjg4hj32g42jh2/424j23gh4h234h2j34j23

I'm not to fuss about some hacker trying to decrypt this to unveil the meaning of all of this, what I'm worried about is sniffing. Cos once the hacker knows that:

gameserver.com/42c34c234c234/ghjghjg4hj32g42jh2/424j23gh4h234h2j34j23

Gives a bonus of +100 it could just keep sending the same request over and over again.

So how do you prevent this?

Talking with few friends these are the possible solutions, but none of them would be either easy to implement or more secure:

  • Moving all (most) of the logic server side.
  • Handshake the first request and respond only to that mac address. (This won't work I think)
  • Changing private encryption key dynamically? How?
  • Encrypt the whole requests, basically using https? (Dont know how though :( )

I'm sure there's an easier answer I dont see :P

A: 

Security is hard. Security when you're trusting the client implicitly is impossible. You need to think about how much effort you're willing to go to in order to protect this, and how much you lose if it gets compromised. Because unless you basically run everything server-side, you can expect that it will get compromised.

If you just want to stop replay attacks, you can do so simply by adding an incrementing "request count" into your command pre-encryption, and discarding any duplicate requests.

But don't be fooled into thinking this is somehow "secure", because it's not.

Anon.
A: 

You could use a variant of what's used to prevent CSRF attacks on websites (I'm assuming you're controlling the server):

  • Have the client make a GET request to http://gameserver.example/userId/givebonus.
    • Generate a UUID or something similar on the server side, which you store in a DB on the server, associated with that userID in some sort of "pending" table.
    • The response to this GET should contain this UUID (like a hidden token in an HTML form)
  • Have the client send a POST request, containing that UUID and the points you want to give.
    • On the server, check against the UUID from the DB and only perform the increment if it hasn't been done before. Delete it from the pending list during the transaction.

(There are a few variants of this, whereby you could sign the token, but I think it would be hard to do a replay on a new UUID in general.)

As a side note, I'd recommend against doing increments by GET requests on http://gameserver.com/userId/givebonus/100. GET is meant to be a safe method, i.e. you can do it as many times as you want and it won't affect the server state; this is by design of HTTP and REST. Clearly, this would cause problems if you take action on a GET. I'd suggest using POST for actions with side effect, and putting the amount and perhaps the action name within the request entity, then.

(Of course, there's no harm in using HTTPS in conjunction with that.)

Bruno
Does not work. Somebody intent on getting a bonus can parse the html. Besides, this is an iPhone app, so the UUIDs will have to be sent to the device in response to a http request, and the attacker can easily call that service.
sri
I meant it as a protection against replay attack, which is what's required as far as I understand. This being said, you're right, the user could make fake requests. To prevent cheating on the amount, this would require knowing a bit more about the entire process involved in the game, I think. Giving out points should be done by the server in response to some actions in the game, not by the decision of the app. Alternatively, the app could sign something, perhaps by generating a public/private key pair on the device (to avoid shipping the same key) and registering it at first.
Bruno