Help with Game Security

Okay so I am working on a game which will award players when they finish a job.

So on the client side when they click a button in a GUI it will run this script

local Event = game.Workspace:WaitForChild("Event")
script.Parent.ButtonLabel.MouseButton1Click:connect(function()
  Event:FireServer("Pay")
end)

Once that event is fired it will connect to a server script located in ServerScriptStorage

local Event = game.Workspace:WaitForChild("Event")

Event.OnServerEvent:connect(function(Player, String)
   if String == "Pay" then
      Player.Cash.Value = Player.Cash.Value + 50
   end
end)

That works perfectly fine, however say some nerd has an exploiter that they can run events sort of like putting an event in a command bar, how would I prevent them from doing that?

If an exploiter could simply run this event

 Event:FireServer("Pay")

then they could easily spam it and get millions of dollars. What do you suggest I should do for a security check so that they cannot spam events for cash?

2 Likes

The way your event is set up, you made it where the client can directly make changes to the server, because every time they fire that event, they will receive 50 cash.

You need server sided checks. Somehow, you need to figure out if they deserve the pay or not, which depends on how your game is set up.

A simple system I would recommend is having a variable for each player, or just an int value called “pay” in their player. Increase the value of that variable/int value by however much they deserve when they finish the job.

Then, instead of setting it up like this:

Event.OnServerEvent:connect(function(Player, String)
   if String == "Pay" then
      Player.Cash.Value = Player.Cash.Value + 50
   end
end)

You can set it up like this:

Event.OnServerEvent:connect(function(Player, String)
   if String == "Pay" then
      Player.Cash.Value = Player.Cash.Value + Player.Pay.Value
      Player.Pay.Value = 0
   end
end)

This allows you to give different amounts of cash for each job, but they can claim it all at once while it accumulates, but the exploiters cannot get any extra by firing the event.

This is secure as long as you can check if they completed their work through the server.

If on the other hand you don’t want it to accumulate and it’s always the same amount of cash, a simple solution is that you can just use a Boolean on the server that becomes true once their work is complete. When they fire the event, you make sure that Boolean is true, then set it to false after giving them the cash.
Again, this can only work if you have a way of detecting if they completed the job from the server, which you should.

6 Likes

*boolean :wink:

1 Like

My bad lol. I’ll edit that

https://i.gyazo.com/54f6832efdc8443f121f0534baa6934a.gif

Okay so I have a local script that when the player clicks on a brick called ShoePrint it will play an animation, then the shoe print will locally disappear. However how would I make a security check that the player has cleaned it locally? Here is the code


Local Script in a tool

Mouse.Button1Down:connect(function ()
	if Mouse.Target then
		if Mouse.Target.Name == "ShoePrint" and  Mouse.Target.Decal.Transparency == 0 and Debounce == false then
			Debounce = true
			local Target = Mouse.Target
			MopTrack:Play() --this is the animation thing
			Player.Character.LowerTorso.Anchored = true --I could use walkspeed but im lazy
			wait(2)
			for i=1, 10 do
				if Equipped == true then
				Target.Decal.Transparency = Target.Decal.Transparency + .1
				wait(.5)
				elseif Equipped == false then
				Target.Decal.Transparency = 0
				break
				end
			end
			Player.Character.LowerTorso.Anchored = false
			if Equipped == true then
				MopTrack:Stop()
				local Mode = "LitFitsJobDone"
				Event:FireServer(Mode)
			end
			Debounce = false
		end
		
		
	end
end)

Global script for the server

Events.NPCService.OnServerEvent:connect(function(Player, Mode)
    if Mode == "LitFitsJobDone" then
		Player.Stats.Cash.Value = Player.Stats.Cash.Value + 8		
    end
end)

I get the thing you’re trying to say, however how could I make the local client communicate with the server to determine its pay when it finished mopping up?

1 Like

Well, we can’t just fire an event that tells the server the job is done. Instead, you need the server to determine if the player has finished mopping everything up.

The way I would go about this is giving the server a little role in here. I’m assuming these ShoePrints are randomized in an area locally. Instead, when the job is started, have the server choose these locations and store them. Then the server would return the locations for the client to make locally. Or if the locations are set beforehand and known to the server, that’s fine too.

The reason that knowing the location of these footprints is useful is because I’m going to assume that the player can only clean the footprints if they are close enough (or they move close enough when they click on the shoeprint).

This allows us to have this sort of security system:

  • Player clicks on shoeprint to clean. The client moves them next to the showprint and starts playing the animations. It fires the server with the parameter “mopping”
  • The server then checks all the shoeprint locations and determines which one the player is cleaning. If it finds one, the one is removed from the list of locations to clean.
  • If the list becomes empty, that means all of them have been cleaned, and that the player finished their job correctly.

Now, this makes it a little harder for the exploiter. But they can still go to each place, fire the event, and go to the next without playing any animation or waiting at all. This would be annoying but still possible and would save them time. That is where we look to see the difference between the exploiter and the normal player.

The client has a debounce of 2 seconds, plus a bonus 5 seconds if your “Equiped” variable is true. So that the player cannot possibly clean two places within that time period, so just include the debounce in your system.

  • If they are close enough, then check the time they cleaned the last one. If it is too quick, you know it is not normal and you don’t count it (or if you know the client won’t ever send that unless exploited, kick them out.) - I’m not entirely sure what your equiped variable does so I’m assuming the debounce is 2 seconds but that’s up to you.

This way, an exploiter would actually have a harder time cleaning the floor through firing events than if he just did it normally. They would have to go to each location, fire the event, and still wait for the debounce.

You can then add ways of detecting someone trying to exploit it if you wanted to. Maybe you check if they managed to move while they are meant to be anchored locally, since you know they get anchored when the event is fired with the parameter “mopping” or whatever you name the string.

10 Likes

I give you praise for a very in-depth answer over two posts. I would have liked it a hundred times if I could, but one like and a reply is all I can do. There is nothing more I wish to say in this comment.
Follow the advice of this man. It is smart.

3 Likes

I’m likely wrong, but wouldn’t an exploiter be able to change Player.Pay.Value?

That would not matter, as we are only changing and checking Pay.Value from the server.

Now, had this game not used fe, then you would definitely be correct, but I did make the assumption that the original post referred to a game with good client server relations.

The reason I proposed the Pay.Value is that he can just adjust that value from the server whenever a chore is complete, which gives lots of flexibility to how much each job gives pretty easily, then it is given when they click to cash in. I just wanted to give a simple idea for how I would implement payment that is waiting to be claimed, with a little more security.
I did of course include that it would only work if the way you check if the job is done is secure, which was what my second answer focused on.

1 Like

Ah, alright, I understand.

1 Like

Thank you so much!

1 Like

No problem.
Glad I could help a member on here :slight_smile:

1 Like