PSA: Enabling LoadStringEnabled doesn't instantly jeopardise your games

Roblox has removed the compiler from the client. Without it, you cannot really use loadstring.
The idea is, if loadstring worked on the client, then exploit creators would be able to make their exploits simply call loadstring() with code they want executed. It would make the process so easy that almost anyone with some knowledge would be able to make their own exploit.

You know how right now you need to recreate the lua vm (cough rerubi) in order to execute code from a string on the client? Well, imagine exploits have to do something similar, except in the C++ land full of taps and checks.
It’s better to have only a few people that can do that, rather than almost everyone, isn’t it?

1 Like

Keep in mind I know nothing about loadstring

EDIT

Look at the post above, mk thanks.

If client-side usage isn’t enabled, that means loadstring() is only able to be fired from the server (obviously), which logically means it would always modify the server (also obvious). This means that there is a chance that, since client-side usage isn’t enabled, that loadstring() was only made to directly modify the server… which doesn’t make sense but if someone thinks I’m on to something then hey, be free to take my hypothesis and expand it to something that makes sense.

Yes but in a perfect world that we don’t live in, honestly anyone even a yokel can find an Exploit to use without any effort, so disabling Loadstring for Client-Side is doing a pretty terrible job from what I can see.

Not every exploit incorporates what’s called a “Script Executor” - I don’t know the technical term, just exploiters call them that or “Level 7s”. The majority of free exploits are “Level 4s” or below, with an occasional level 7 coming out once for a preview, but when they get patched it goes paid. Level 4s only allow usage of certain commands (basically mini admin commands), such as “kill player”.

Most level 7s are paid, and the ones that are free would probably have limited features to the executor (Full lua executors and other stuff, I don’t understand the differences between this though).

Therefore, if you did enable Loadstring for Client-Side, the level 4s would be able to all incorporate Loadstring in order to replicate the effect of level 7s. Most of the 15- community wouldn’t bother paying for an exploit on a “lego game” (as they would put it), therefore they would turn to the free exploits which would lack executors (unless a free one had conveniently came out that week). If the level 4s had access to loadstring, whilst they’d probably look trash as executors since they don’t usually come with custom built UIs and just use things like command prompt for appearance, then this part of the community would be able to execute scripts without effort, as you mentioned, however that is in the case that loadstring becomes client-side.

I don’t know too much of the details since, well, I’m not an exploiter, nor do I know anything about how Roblox handles loadstring, but I hope this helps clarify some things about free vs paid exploits.

1 Like

That’s a really interesting use of loadstring, I like the idea of whitelist not blacklist

@superhudhayfa
as far as I know exploiters can’t simply run code directly on to the server by themselves, that’s not what level 5/level 7 means. The reason why you sometimes see exploiters making changes to the server is because of hidden backdoors brought in to the game through malicious plugins, malicious developers, etc. With loadstring enabled, exploiters can send code data to this backdoor and have it directly executed on the server! This is why loadstring can be dangerous; if the server is directly executing code sent from clients.

1 Like

I don’t recall writing anything about saying that exploiters have the ability to write code to the server. I’ll re-read everything I said and edit this appropriately to avoid misconceptions.


Sorry, this is a fault in how I wrote the post. I didn't mean that level 7s have the ability to execute code to the server, just that they had the ability to execute code, through whatever means, that edits the client - I don't know the intricacies of how this works. With Loadstring enabled on the client, assuming that client-side usage would only affect the client and server-side usage would only affect the server, level 4s would be able to replicate the effect of level 7s. If loadstring enabled on the client allowed direct access to the server, then that's a different matter.

I’m being quiet ambiguous since I don’t know the whole details, so if you can’t understand what I mean then… :man_shrugging:

I think you greatly misunderstand what “disable loadstring on the client” means. It means the client is not compiled with a Lua compiler in its binary at all. Without a Lua compiler, people are forced to go through dozens of hoops just to get proper Lua structures formed in memory as opposed to calling a function that does it all for them.

Loadstring on the client is simply a huge security hole.

@superhudhayfa I wrote this on the topic which has more info on that stuff Exploiting Explained

3 Likes

I see now that you have pointed it out, I didn’t understand that part before, I don’t have a good understanding of how the compiler works and all, as I am wondering if it doesn’t have a complier how can it run Local Scripts? But I’ll leave it there as this is off topic and I can research on my own.

Thanks for the insight



You shouldn’t use loadstring for the exact same reason JavaScript developers are heavily warned against using eval: You could open up an opportunity for a XSS attack.

Also, if you have to use loadstring, then that means you’ve designed your system poorly. You should never have to execute arbitrary strings as code in your system. Never in my 11 years of programming have I had to do this.

So I agree with OP’s points that a lot of people misunderstand why it’s considered a risk, but I would still heavily recommend never using it except for experimental projects.

2 Likes

Except it doesn’t apply here. If you are letting the client tell the server what to loadstring (and you aren’t making a script builder or such), then there is something seriously wrong with your code.
On the other hand, if you know exactly what you’re doing, you will never “open up an opportunity for an attack”.

It does apply. This is why it becomes such a big vulnerability even in the professional world. For instance, imagine you need to run loadstring, but you need to inject a few parameters. That’s easy, as you can just concatenate the string before loadstringing it. However, what if those parameters are coming from user input? If that’s the case, you have an exploitable system for the end-user to inject code.

For instance, maybe you have an input that allows the user to choose their name for an RPG. When you do that, the system runs loadstring on some code that uses the name to print it out (or whatever):

function AcceptName(name)
   local code = loadstring("print('Hello ' .. name .. '!')")
   code()
end

Now if the name argument originates from user input, the user has the power to inject any code:

AcceptName("Bob') DoSomethingMaliciousHere() print(")

Which would resolve in the code:

print('Hello Bob') DoSomethingMaliciousHere() print('!')

The point is this: many younger devs will probably overlook small things like this. It happens in JS all the time, and it can happen in Lua too. Now, I am aware that this is more akin to SQL Injection, as XSS typically involves another client executing the code, but the concept is the same: allowing arbitrary code to be executed that might have been manipulated by an end-user.

3 Likes

This is exactly my point.
XSS vulnerabilities usually require the client to mess with the parameters it passes to the server. However in the roblox world, you should not let any player pass any arguments for your loadstring. If you do that, then it’s your fault if the game gets exploited, not loadstring’s.

In real world, I can’t think of any scenario where your game would need to loadstring anything a client sends, unless it’s a scripting game, in which case, sandbox is a must be.

2 Likes

Ok so I think we’re actually on the same page here. My point is that many young devs don’t realize they should avoid doing that, which is why it’s better to just avoid using loadstring

3 Likes

But loadstring is basically recompiling (one of the heaviest tasks Lua does) which can have a performance penalty if used a lot.

Compilation itself is slow and still a lot faster than other languages, but once compiled, it runs at the same speed as any other script. A lua-in-lua VM would definitely run slower.

2 Likes

Server-side scripts are never shared to the client, only replicated.
Please correct me if I am wrong, it is not been long since I became a new member.

Yep, the objects replicate (if the Script object is in a place that should replicate), but the bytecode does not. It’ll just be an empty container on the client.

Be careful with ModuleScripts that contain code that is normally only executed by the server, as the bytecode of ModuleScript source will be sent because the game doesn’t know who will be executing that code, so it has to be made available on the client too. It’s good practice to keep all your server-only stuff in ServerScriptService / ServerStorage for this reason.

1 Like

I’ve been doing some research on game security recently. You are correct that it is a complicated subject.There are several methods for securing a game, but one of the most crucial is maintaining the integrity of your data. It’s critical to keep your data safe because it’s what keeps users engaged in your game. The most common way to do this is to ensure that your game is not susceptible to cheating. When gamers utilise tools to obtain an edge over other players, this is referred to as cheating. There are other methods to cheat, but I’m mostly referring to aimbots. It is also possible to cheat by getting an unfair edge during games. Unfair gaming occurs when players take advantage of game faults or mistakes to obtain an edge. Cheating is also feasible through the use of exploits or cheat codes. Cheat codes are essentially hidden codes that provide gamers with an advantage over other players. It’s critical to keep your game safe since it keeps it alive. If you want to keep your game alive, you must ensure that it is bug-free. A “bug” is a flaw in a game that allows players to gain an edge over their opponents. It is critical to safeguard your game since it keeps gamers engaged in it.

1 Like

In the AcceptName() function can’t you just do a sanity check to check if the user input does not contain (") or (’)?

function AcceptName(name)
   if string.find(name, '"') or string.find(name, "'") then return end -- my addition

   local code = loadstring("print('Hello ' .. name .. '!')")
   code()
end

Now no client can inject code in this case.

That solution doesn’t scale.

  • You would have to apply this on every client input consumer. An exception case can be made for a module that supports middleware and if all communication is filtered through it.

  • You may want to accept quotation marks in your client input consumer. Blocking against quotation marks therefore wouldn’t make sense in that scenario.

  • Quotation marks aren’t representative of a code snippet. The whole problem relies around bad design allowing clients to pass anything executable.

The case I made when this thread was created was that LoadStringEnabled does not immediately put your experience’s security at risk. The discussion they were having is that careless or bad design can lead to a client being able to leverage server loadstring permissions and have it execute code.

The only foolproof solution against a client tricking the server into executing code is good design or not having it enabled. Beyond that, other proposals such as checking for quotations in input bank on assumptions about the incoming data.

3 Likes