Sandbox Breakout

I was reading on the sandbox page for lua,

It mentions that some functions are unsafe to use because they use the global environment, I’m wondering how someone could actually break out of the sandbox environment using a function though? My initial idea was that they could re-write the function to do whatever they wanted but that means overwriting the function which would break it.

for example, if I wanted to sandbox this function:


local Kill = function(id) Player(tonumber(id)):Kill() end

Is there anyway someone might be able to redirect what it does so that, instead of killing someone it could apply force or even set them to admin?

Thanks.

There’s no way for people to redirect local functions, since they’re local to the file - unless they change parts of the file itself

However, in your case it isn’t possible for them to change the file. The function you posted above uses Player:Kill, which is a serverside command, meaning that file must be serverside to work. Clients can’t overwrite serverside files from their side, so it’s impossible to change it

Forgot to mention, I’m having to handle scripts serverside (I am aware of the risks), because of complications linked to script syncing and other stuff, basically I’m wanting to make sure that if I gave them access to a sandboxed area with certain functions that have ties with variables in the global environment, they wont be able to break out.

What do you mean? Script syncing? What are you doing? Can’t you just use convars or any other kind of network variables?

I’m not exactly sure what you’re asking, but I can tell you sandboxing ain’t easy.

In a sandboxed environment you can still do really shitty stuff like this.

[lua]
("."):rep(999999999)
[/lua]

This used to crash the game, now it just allocates a shitload of memory, but it still makes the game lag balls.

Thanks for both replies, to answer your question MPan, I am recreating an addon that I had made that gave players the ability to script ‘chips’ for different devices like a screen so that the client can run code on it such as Screen.AddText etc, I’ve realised though that it doesn’t work as I would like on clientside, if a new player joins the server, any variables created on previously connected clients wouldn’t exist on the new one, it’s not very easy to explain and I’ll probably be able to explain it better tomorrow.

[editline]11th December 2016[/editline]

Hey Parakeet, Thanks, I’m happy to make a blacklist system that blocks functions such as that one, I’m more concerned with a chance of users accessing global functions such as SetUserGroup and the others.

Okay now that I’m fully awake, I’ll explain the situation and goals better:

I created an addon that supports client scripting, the client can code scripts for entities like displays, the scripts were stored serverside and ran clientside, this worked perfectly fine and I added support for user input, the real problem came when I realised that if a new player joined the server, their client would have no knowledge of any input or further code input onto the device aside from the base script. The solution I came up with was to run it (reluctantly) serverside, so that variables and everything else were stored and clientside functions could be called such as adding text to the screen, this way input and use of custom variables / functions will not be tied to the players on the server.

Because the code has to be ran serverside (and again I am aware of the risks involved with this), I need ways to protect the addon from being a vector for attack, my current system includes a script that isolated (sandboxes) the client scripted function with setfenv, it then also has a ‘tick quota’ so that the user cannot spam the server with code.

My primary concern, is that if I provide the sandboxed area with a custom made function such as Display.AddLine, which modifies / appends to a table in the global environment, is there anyway for them to modify that function to make it do something else?

More Graphical Explanation:


--Global Environment

MY_TABLE = {}

function AddToTable(contents)
table.insert(MY_TABLE, contents)
end

local Sandbox_Environment = {print=print, AddToTable=AddToTable}

function SANDBOXED_FUNCTION()
AddToTable("Testing")
end

-- Sandboxed Environment
local Boxed = setfenv(SANDBOXED_FUNCTION, Sandbox_Environment)
Boxed()



That is a demonstration of what I mean, I have given that sandboxed environment access to a function that CAN modify the global environment, does this provide a way for someone to modify that function to do something else in the global environment?

Thanks.

What you want sounds really similar to wiremod and specifically E2. Consider using that.

With only those two functions available in the environment, the outside can’t be reached. I’m failing to understand what exactly you’re even trying to do. You say you have an addon that supports client scripting. What precisely do you mean by that? Why does client code need to be sent to the server if it’s code intended for the client? Are you aiming for clients to be able to share code between each other? Why does the server need to execute code that is meant for the client in the first place?

Hey again NeatNit, you’re correct, it really is similar to E2 but the problem I have there is that I don’t have the time to make a custom language from scratch and I wouldn’t be happy ripping functions from it anyway. I just wanted to be careful more than anything because I wouldn’t want to be held responsible for adding a form of backdoor to my addon, thanks for the suggestion and I’ll definatley keep it in mind.

[editline]11th December 2016[/editline]

Hi sannys, in short the addon allows players to create scripts for entities like a screen/display.

In the first version, the player could create a script, send it off to the server (where it is stored) and when the code needed to be ran, each client would ask the server for a copy which would then be sent to them and executed clientside, however - lets say that we have a script setup so that under certain conditions a variable is created, if that is met and the variable is set, when a new player joins and executed the script that condition has not yet been met (because they are starting the script from the start).

My workaround was to have the script run serverside so that a client doesn’t have to be present in the game for them to keep up with the current state of a script, everything is stored on the server.

Sorry for the convoluted answer, my best way of describing this is probably with Chessnutt’s video of GTerminal 2 development:

https://www.youtube.com/watch?v=jLnvrEk8qdo

That is what I’m aiming for.

In response to your question, it is to share code yet, not only this but if the code is executed clientside there is no way of me to safely keep track of what stage the script is currently at, if a condition is met and a variable is created that doesn’t initially exist, how would a player that just connected know that the condition was previously met and create the variable as such?

I meant, why not literally use wiremod? Or just E2? Give proper credit and talk with the Wiremod team about it to make sure you’re not doing anything wrong/illegal :wink:

I see what you mean, I think it’s more of a case of aiming for a custom system, I wanted to tie it into a gamemode (RP) so the use of toolguns wouldn’t be favorable, I know there are ways around it but it just seems like it would be more of a hassle to modify E2 (With permission) to my needs than to make something like this, it’s not a bad idea and I’m actually leaning towards that now to be honest. :smile:

But currently I’d still prefer to use this lua setup, as long as players can’t abuse it.

I think I’ll mark this as solved for now as from what I can tell there are no easy ways to break out of a sandboxed function. Cheers everyone.