I have a dozen or so games and never worried about security, moslty because nobody plays them. However one of my larger games was hacked and the hacker laughed at how horrible my security was, I laughed with him. This is what I heard about security:
Anything in the client is visible to exploiters(local scripts, replicatedStorage, etc)except scripts in Workspace
Exploiters can fire remote events, and look at local scripts to see what parameters to use. This would make sense with point 1.
Exploiters can never acess ServerStorage, ServerScriptService, etc
I am not sure whether these things are right or not. Are you suppose to somehow try to not let the exploiter access the hidden things in the client? Do you use secret folders or something? How can you ban them? What did I get wrong? Can you use free-model scripts? How do you go about making security scripts?
You can try and hide it, but it can be found and manipulated if it’s on the client and the attacker is determined.
Your goal is to keep important stuff that affects gameplay managed on the server, and miscellaneous stuff on the client. This limits impact on the server and restricts things to each client. With that said, when it comes to client security the primary goal is to make it harder for more capable exploiters.
Don’t worry about attempting to hide or obfuscate your client-sided logic. It is fundamentally impossible to completely hide it because it exists on the clients machine, which they have full control of. Obfuscating or hiding your logic won’t provide any security benefits, and is pretty redundant because it won’t prevent a dedicated malicious actor.
Focus on implementing a correct client/server modal. Validate all information from the client and have the server take an authoritative stance. It sounds like you are relying on information sent from the client. This is a big no, never trust the client. It is not a trusted source, as, yes, data can be manipulated on the client. A prime example would be a graphical shop on the client. A secure setup would be the server being informed you want to purchase a specific product, the server finding the price of the product and deducting that from the clients wallet, and awarding the item. An insecure setup would be the client providing the cost and the server acting upon it (the client can manipulate the cost value, and therefore the server will act upon the value provided by the client, E.g. 0).
Everything, outside of instances under ServerScriptService and ServerStorage, is visible to the client. A script instance under workspace is visible, albeit it is useless because bytecode isn’t replicated to the client.
It comes down to how the actions of the player are verified in the game. Your game should should be “server authorative” which means the clients actions are being sent to the server to be verified, such as a payment process. You would store a users currency on the server and only update the cash from the server. You would not trust the amount being sent from the client telling you how much it’s earned or that it’s paying the correct amount.
These are called “sanity checks” and it’s the lack of these that are why most games get exploited.
That would be bad. Any exploiter could trigger the remote and change their data. You should have something that detects an event requiring a data change on the server. This way they have no way to make direct changes to their data.
You want to avoid something along the lines of (as a flat example):
-- Client
ShopEvent:FireServer("Turtle hat", 100) -- Product, cost.
-- Server
ShopEvent.OnServerEvent:Connect(function(Player, Product, Cost)
if Player:GetMoney() > Cost then
-- logic
end
end)
as the client can manipulate the cost and the server doesn’t validate. Instead:
-- Client:
ShopEvent:FireServer("Turtle Hat")
-- Server
ShopEvent.OnServerEvent:Connect(function(Player, Product)
if Player:GetMoney() > GetProductPrice(Product) then
-- logic
end
end)
…as the client can no longer manipulate the product cost.
Fundamentally it is the same concept which you just mentioned. It is indeed insecure, since the client can set an arbitrary changeValue, E.g. FireServer("Money", 1000000). I’d suggest you find an alternative way to handle the process.
Thanks, is this the only kind of security needed? to never trust the client. Any tips on making some sort of banning system, or are they generally not needed?
I’d avoid anything which kicks or bans suspected malicious users. It is possible for there to be false positives, and it also allows them to gain a better idea of what action resulted in them being flagged and then avoiding (although, this can be avoided by using a honeypot and delaying the ban date). I would still recommend against it though.
For the most part, yes, don’t trust the client and ensure you have an authoritative server/client modal. It helps to manually map out and fuzz points where the client communicates to the server. It is worth mentioning physics based exploits, such as speed or position. These can be mitigated (use the devforum search feature) by validating character position data on the server, however I feel as if they fall outside the scope of this thread.
Hell yes, take this:
for _, v in pairs (workspace:GetDescendants()) do
if v:IsA("BasePart") then
game.ReplicatedStorage.RemoteFolder.DealerEvent:FireServer(v, false, "Anchored")
end
end
… as an example. It is game-breaking. I can change the names of events under ReplicatedStorage, disable scripts in ServerScriptStorage, unanchor all parts in the workspace, etc.
It is fine though, make sure you take the time to review your current code-base and you will be able to easily prevent similar issues in the future.
In this case, it depends. The most simple option is using DataStores in-game. Mark that they are banned, save that data, and check whenever a player joins the server. If they are banned, kick them. If you want a remote method, it gets more complicated.