Loadstring() - how to check the code on malicious functions

Hello,
Today I come with idea to make a user console, where you can execute Luau code on server, and I have a problem.
As I know, you can call require(), loadstring(), script, destroy / remove / ins.Parent = nil as Server.
And I need to detect if script has these functions, which I mentioned above.

My method:
Player writes a code, and sends it though RemoteFunction. Server catches the request from RemoteFunction, and then checks the code on malicious functions using string.find(A, "require") and like that.

I tried to use debug.info and tried to loop though getfenv(any number) which gave me only; _G script, shared.

So the question:

How can I check if Player calling malicious functions (require, script, loadstring) before or when loadstring() is called?

2 Likes

Why is your methdo not working? Can’t you use string.find?

I know about obsufications, like;

local a = string.reverse("eriuqer") -- "require"
[a](id)

And I think that string.find method is not really safe

The only method I could think of is sending the script to an external server that you run which essentially runs the code in a sandboxed environment where it can detect any calls to malicious functions like require() and then if it does detect anything like that your server returns false to tell the game to not run it or true if it’s safe to run.

It’s almost impossible to string.find any malicious functions considering obfuscation techniques (unless you specifically block those too but just be cautious).

Well I heard about Sandboxed servers, but I don’t know how to use them and how to get them

try this

local function safeLoad(userCode)
	local safeEnv = {
		print = print,
		pairs = pairs,
		ipairs = ipairs,
		math = math,
		string = string,
		table = table,
		-- add whatever
	}

	setmetatable(safeEnv, {__index = function() return nil end})

	local fn, err = loadstring(userCode, "UserCode")
	if not fn then
		return false, err
	end

	-- apply
	setfenv(fn, safeEnv)

	return pcall(fn)
end

local success, result = safeLoad([[
	return game
]])

print("Result:", success, result)

Cant you just use Find All / Replace All? I just created 3 scripts with a blank require and i searched require in find all and it worked

He wants users of his game (I’m guessing) to be able to run lua code like an executor on the server but restricting their usage to safe functions.

Ah, ok. Maybe he could just block some things like detect certain functions. It seems easy enough to do that

You need to factor in obfuscation.. It’s not as simple as you think.

ah okay, makes sense.
I found a link to a post that talks about preventing access to certain services and restricting code using LoadString. Other than that, the only other option in my opinion is a custom interpreter to allow players to only use limited, handpicked functions

Nice try, I tried do something like that but with blacklist method.

Still executing require function.

I would basically create a Flask server in Python or an Express server in node.js and create the ability to post request to your server with the users entered lua code.

You can then download Lua U here: GitHub - luau-lang/luau: A fast, small, safe, gradually typed embeddable scripting language derived from Lua

And you would essentially overhook the malicious functions like require before the server attempts to execute the Lua code and replace them with something which triggers the server to return false - to tell your game to not run it.

I’m not sure there’s any full code examples of this on GitHub but yeah.

Oh yea and if you decide to do this: be careful that the Lua isn’t actually affecting anything on the server running the code.

But isn’t it requires HTTP Service?

Yes it would require HTTP service

Then it could be overloaded with requests.

You can add debounces and other security measures and also DDOS protection on the server using services like Cloudflare.

In anyway, I don’t see this really useful, seems hard to me

check these topics:

1 Like

There isn’t an easy way to directly check if a player is using those functions because of stuff like obfuscation.

Your best bet is like what @kaanture36448 said, using loadstring and setfenv in #7. You’d have to create a custom environment table with whatever globals you want to allow (or can use metatables and __index, doesn’t make much of a difference iirc). However, controlling Instance access is a bit more complicated - you’d either have to wrap it yourself or use a module (shameless self plug to my sandboxer hehe)

In my opinion an external server to read/parse/check/whatever the code is completely unnecessary and a waste of resources