Edit: buildthomas is correct. It doesn’t matter how difficult a client-based exploit protection is to bypass, if anyone does it, they will share/sell their exploit to other people and hundreds of people will end up using it. Server checks are the only reliable way to prevent exploits. I also personally would not use the module for its other features as it is basically a glorified copy of the existing remote system built into Roblox.
The comments you see below are old comments from when I was inexperienced.
I don’t recommend this kind of practice for several reasons:
Security through obscurity is not real security. “Secure” here is somewhat of a misnomer for that reason. Once an exploiter deciphers this mechanism, they can just as easily hook into it. (see bottom of post for some ways in which you can easily break this)
This could lure less experienced developers into the trap of leaving out other kinds of validation on remote events. That would lead to bad situations once an exploiter does figure out how to circumvent this.
Adding a key to every network request is wasting a bit of bandwidth, considering that if proper server-sided checks are implemented, you can achieve a much higher sense of security for no additional bandwidth hit.
All this seems to do is add a random number to the request that you generate on both the server and client. So all an exploiter needs to do is copy over the configuration of the Random object from memory and start sending requests with the right numbers. Moreover, they can still intercept requests and transform the rest of the parameters in the request as they please since they do not correlate with the random number.
Or even easier, they could grab a Lua reference to the Port object that they are interested in using from memory, and then start invoking functions of that object just like the localscripts would do.
TLDR: Security through obscurity is not real security. Server-sided checks, server-sided checks, server-sided checks.
It does not stop them entirely from exploiting, it is simply a wall of difficulty. The majority of exploiters are simply running code injectors, and do not have the know-how themselves to enact the vulnerabilities you suggested.
I should’ve clarified that it’s not perfectly secure in my original post. A smart enough exploiter could definitely bypass it. The client should only be used for sending input to the server and displaying UI on the client, while the server handles almost all actual activities.
As for using more bandwidth, an extra number is only a couple extra bytes.
This systems primary use is to prevent the average exploiter from automating your remotes, as well as work as a decent organization tool. It will not however stop people with the expertise and determination to bypass it, and it is not a replacement for a proper server-client model.
All it takes is 1 person to write a bypass for it. Sorry, but like thomas mentioned, it’s preferable to use a proper client-server model and not apply a false sense of security.
As i mentioned in my reply to buildthomas, it is not meant to replace a proper client-server model. It works as an addition to it to prevent easy automation by exploiters.
Also, a bypass could not be written in lua unless the code injector they were using built in tools for them to access all script environments and local variables. Otherwise the creator of the code injector would likely have to bypass the network themselves and release the exploit as an update.
Another thing i should mention is that exploiters could not either guess the randomseed or copy the random object from memory to send requests, because this would de-sync the server from the client. This could be detected easily and kick the player. This functionality is actually already built in, though it is disabled by default.
The only option to bypass it is the other way you mentioned, grabbing the lua reference for the port or channel from memory.
It doesn’t matter if they know the code or not, they still cannot bypass it without finding the port in the memory, which cannot be done from most simple code injectors.
Edit: New code injectors have incorporated this ability, so this is no longer true.
This seems overly complex and not really needed when it comes to networking, this can also be bypassed in less than 10 lines of code by an exploiter, making it basically useless.
If you’re gonna go down this road of networking security, make sure it’s actually worth it and make sure you know what you’re doing, otherwise it’s gonna do nothing to stop or even slow down exploiters.
but in the end the exploiters will be able to bypass anything you do if you give them enough time
Thats used through the module heirarchy, which requires access to the original channel that was created when GetChannel was called. It’s not accessable by requiring the module directly.
The code isn’t very straightforward to understand, it uses a way of organizing I like to use that splits functions into separate modules so it’s visible in the explorer rather than sifting through hundreds of lines of code.
You don’t have to understand the code to use it though, you can just follow the API. The difficulty in understanding only further aids the prevention of exploits.
Note: “a bit”. If you read the whole paragraph you’ll see the whole reason: it’s silly to use more resources over the network when server-sided checks are much more secure, and don’t consume those resources.
While it’s good to be thinking about security when implementing the client-server model, I think it’s more appropriate to use RemoteEvents and RemoteFunctions as if they were network sockets rather than use monolithic network event handlers
sockets don’t validate their own data - it’s always the server’s job to make sure that nothing unexpected happens
I don’t see the problem here. It is stated multiple times you still need to utilize a proper Server-Client model, yet you seem to ignore such fact. This is only intended as an additional layer on top of a proper model. Now you could argue it’s pointless if your have a proper model, but what harm does it bring to provide an additional layer of security? I see none if used as intended.
Not sure what you are referring to. I don’t see this mentioned in any post I’ve replied to.
The original title of this thread was “Secure network system” and the OP did not mention this. This is why I pointed it out because it is in a publicly accessible category, and you can’t assume every reader to be as knowledgeable about security that they can see through that.
Correct, and see my post above for reasons why (I hope you’re not asking me to repeat myself!). I’m not saying it won’t decrease the number of successful exploiting attempts in a game, I’m saying that I do not recommend wasting development time on this over writing proper checks on the server, because the latter is much more secure.
Unfortunately, your solution is unnecessary and easy to bypass, as mentioned in other places in the thread, you’re only going to get some decent security if you design your remotes properly in the first place. Have fun with this bypass proof of concept…
--[[
RemoteFunction manipulation through editing Roblox' great ol' metatable, works on exploited game clients.
]]
local mt = getmetatable(game.Workspace)
local invokeServer = mt.InvokeServer
local __index = mt.__index
mt.__index = function(t, k)
if k == "InvokeServer" then
return function(remoteFunction, ...)
print("RemoteFunction " .. remoteFunction:GetFullName() .. " sent something: ", ...)
local args = {...}
--[[
Insert manipulation logic here
]]
return invokeServer(remoteFunction, unpack(args))
end
end
return __index(t, k)
end
Maybe not in the OP, but we could have made the suggestion to fix this lack of information instead? As someone whose dealt with the exploiting community within a very personal level (I’ve been members of the various communities before and know a lot of them personally, mainly to figure out ways to better secure myself against them), yes the best line of defense is ensuring you have proper Server-Client logic with the Server validating against requests effecting the game logic. However, I still don’t see the problem with an additional layer of security along with the proper practices. Additionally, how it is a waste of development resources if the resources are already provided? You didn’t have to make this module, it was already provided. The only “waste” would be taking the time to learn it, which the model seems fairly well documented. This may not be recommended for new users, but I still don’t see an issue with additional layers of security as long as they are all implemented accordingly.
EDIT:
AA when you reply to the wrong person @buildthomas
That was kind of the point of my post… adding the necessary information that wasn’t included and then recommending to use the proper model instead where you can.
This might be a personal thing, but it seems like a chore to pipe everything through this module (thereby also creating a dependency on this module), and I’d rather spend that same time writing the corresponding check server-side instead (do people think these take hours to write or something?) and keeping my interactions with remotes clean and easy to understand (closer to the RemoteEvent, not obfuscated through this or any other module). You’re basically putting development time into making your code slightly more secure by doing the former, rather than spending it making your code lots more secure with the latter.