I’m working on a game(FE enabled) where I’m storing the player’s data in a folder(containing values) under the player in Players . That way it is easy to access for both local scripts and server scripts, but how prone to exploiting would that be?
Not any more (or less) secure than storing it anywhere else that the client can access.
How prone would it be to exploitation though?
You shouldn’t store data like this. Anything the client can see can be altered, even if it doesn’t replicate. A̶s̶s̶u̶m̶i̶n̶g̶ ̶t̶h̶e̶ ̶c̶l̶i̶e̶n̶t̶ ̶r̶e̶f̶e̶r̶e̶n̶c̶e̶s̶ ̶t̶h̶e̶s̶e̶ ̶s̶t̶a̶t̶s̶ ̶a̶n̶d̶ ̶a̶s̶s̶u̶m̶e̶s̶ ̶t̶h̶e̶y̶ ̶a̶r̶e̶ ̶l̶e̶g̶i̶t̶i̶m̶a̶t̶e̶,̶ ̶y̶o̶u̶’̶r̶e̶ ̶g̶o̶n̶n̶a̶ ̶h̶a̶v̶e̶ ̶a̶ ̶b̶a̶d̶ ̶t̶i̶m̶e̶.̶
Edit: Meant to say that you shouldn’t rely on storing reference data with values on the client since it’s a lot more insecure than sending server-secured data from a remoteevent and storing it in a localscript/module. Just in case, always double-check with the server.
I’m assuming you are supposed to put data in serverstorage, and when clients wants to access the data, it will call a remote function returning what it needs. Is that correct?
Can you give an example where a hacker modifying ValueObjects locally would be more harmful than a client getting stats from the server?
That’s only a problem if you don’t validate stuff on the server. It’s 100% fine for the client to assume it has x value so long as the server knows the proper one.
What do you mean by validating it? How would you do that?
RE your edit: I’m still not convinced that storing *and modifying value objects from the server is more insecure than retrieving data from the server since hackers can just ignore whatever data the server hands to the client anyway.
EDIT: Really, the only reason I could see why you shouldn’t store stats like points/etc. in a ValueObject under Players is to prevent hackers from peaking at how much money another player has. That’s it.
Yes. You should also practice caching stats after receiving them for unimportant things like displaying currency, etc.
Two big reasons for me, personally:
Value objects are much easier to access and manipulate than variables stored in code
You’re relying on automatic replication from server changes which you have little to no control over
You could store the data somewhere both the client and server can see. As long as FE is on (which it’s forced now), the client can change the value to anything but it won’t replicate to the server.
So let’s assume you want to buy something. The exploiter has given themselves 1,337 points. The client tells the server “I want to buy this.” The server then checks to make sure the client actually has enough money to get it, and if they do, it lets them. It’s literally as simple as this:
function buy(plr, itm) if plr.Money - itm.Price >=0 then --The player has enough money to get the item. --Give them the item. end end
The rule of thumb is to trust the client when it comes to displaying things (e.g. thier points), but never trust them when buying things.
I do not recommend caching stats, especially ones like points. It’s crucial that the client knows exactly how much they have. Just add security against them spamming remote functions if you want their data on the server and you should be okay.
Making something more obscure has little effect on security. Odds are these values are going to end up being used for your remotes, and hackers tampering with remotes is pretty much a given.
True, the server does coalesce rapid changes to a value in the server to just one change in the client. For stats like money or whatever, this probably wouldn’t matter.
Store real stats for all players on the server, preferably using a ModuleScript that returns a table.
Send stats to each client whenever an important action is done that affects the server stats to keep the server and client versions of the data in sync.
Do things on the client when you need things to be smooth, or to happen quickly.
Examples: Animations, graphics, anything UI based.
Verify integral components on the server.
What this means: Do an action on the client, send the info about the action via a Remote to the server, the server verifies the legitimacy of the action (can the client actually do this? Let’s use our version of their stats to check). If they can, it replicates to other clients, and affects them/the real stats on the server. If not, no big deal - the only person affected is the one that isn’t synchronized with the server, whether that be because they’re manipulating their stats or there’s latency.
I highly disagree. If something (like coins) is read-only on the client and gets a lot of changes over a small period of time, it’s very inefficient and pointless to get updates for EVERY incremental difference. This clogs up networking when deployed on a large scale. I only request up-to-date versions of stats when I need them, not at all times/when they change.
I see where you’re coming from. That’s actually a pretty good point.