Securing remotes against replay attacks

Part of my combat system verifies hits by firing a remote from the client with data about the hit. (Where was the client aiming? Where were they facing?) How can I secure this remote against replay attacks? E.g., an exploiter successfully hits their opponent. As the verification remote fires, the exploiter sniffs this remote, and fires it again. Because the remote is identical to a successful hit, it damages their opponent twice.

From what I’ve read, people defend against these attacks by creating a one-time token that prevents the message from being sent again, but I’m not sure how I could implement that in the context of Roblox.

Timestamps wouldn’t work as an exploiter could fire the remote with a different timestamp, with every other argument identical. Tracking each verified hit and preventing that exact same one from being used again wouldn’t work, as it’s possible for two hits to be identical without exploiting.

Any ideas would be great!

correct me if im wrong but i dont think thats something you have to worry about. if you use sanity checks and/or a cooldown and the exploiter sends the same data again, it will be invalid and it wont do anything

1 Like

Thank you! Your reply made me think of an idea, validating input on both the server and the client, making replayed attacks unviable.

My system will show the effects on the client instantly, while the actual validation will be performed on the server.

Let me clarify what I mean by this reply in case anyone runs into the same problem.

My previous system detected hits on the client, then fired a remote with data about this hit to the server, which then performed validation. However, gathering data solely from the client for validation made replay attacks possible. By detecting hits both on the client, and on the server, replay attacks won’t work.

@AsynchronousMatrix, please feel free to add on. (I noticed you typing)

Aha, here comes my totally mad idea on how to create security & embed it into remotes! While making an exploiters life impossible to deal with!

The Handshake!

In my opinion, every remote system at hand should have a handshake system, be this through the middleware provided by your remote module, or through an obscure method to set a handler for remotes.

The handshake’s goal is to tally up the remote count on both the client and the server, and if either or is outdated or not accounted for, then a third party has started to send remotes on your behalf :smile:

The Random!

This is more of a signature system, but essentially on startup when the client first starts, the server will send os.time or something alike to the client, giving them quite a big number.

This numberObject:Next() will then be thrown into the remote request, now you’ll have an obscure way to fetch and retrieve server synced values.

(for reference, numberObject is a Random | Roblox Creator Documentation)

The Common Sense

Protect your remotes as much as you want, but ultimately secure your server! Developer services to catch out bad arguments and what not, if your server isn’t secure, adding a middleman will not be the solution.

1 Like

Ah yeah I just wanted to throw down some ideas, feel free to use them or not :smile:

Implementation can be really tricky to do though…

1 Like

Actually, I played with this idea a bit myself! I used a vanilla Lua 5.1 implementation of SHA-512 to hash positions of players on the server. Every time a player moved, I set an attribute to this hash from the server in ReplicatedStorage. By doing this, and requiring the client to send this hash back, I could verify that they actually saw them at that position. They couldn’t fake a position that never replicated onto their client because they wouldn’t know the key that was randomly generated using the server’s GUID.

I removed this as it was straining the server too much, but it’s a fairly foolproof way of forcing the client to only pass info that 100% came from the server.

You might still be able to do this, but make sure you utilise the parallel programming roblox offers, it would run this in an entire different luau VM so it shouldn’t have an effect on your game.

Though this is quite performant never the less, maybe there’s a SHA-512 equiv you can utilise that is more performant?

You can find the Sha-257 implementation here though, I find this to be performant and might provide the same layer of obscurity:

1 Like

Thanks! Honestly if I were to use this method, I would use a more performant algorithm and use it on something that updated less quickly. SHA-512 is already overkill for passwords, a non-cryptographic hashing algorithm would be more than fine. Probably MD5 or some other fast but relatively secure one.

1 Like