lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


There's generally two approaches to making stuff secure(-ish). Carefully checking & restricting to fit into existing structures and not cause problems, or quoting (using built-in functions) to contain with limited power. If you look at SQL injections and tons of other problems, you see that the first approach causes issues all over the place.

On Mon, 10 Jul 2023 at 08:31, bil til <biltil52@gmail.com> wrote:
I would like the user to enter some variable name, or just some name
which then I also want to use as name for a Lua global object.

If you *only* check for lexical compatibility, what happens if someone chooses "local", or "table", or "debug" as the variable name? If you check that the thing isn't a reserved keyword (e.g. by Franciso's suggested method), it won't immediately crash. But how do you check your user isn't accidentally (or intentionally) overwriting your own program's data (or library functions)?

On 2023-07-10 13:02, Francisco Olarte wrote:
I think you can combine all in a one lines ( use three or more [for]
clarity,  this is for easy cut & paste ):
function ok_var(v) return string.match(v,"^[%a_][%w_]*$") and load("local "..v,nil,'t') and true end
Experts may correct something missing, but unless you need a really
complex one that should be enough for a user.

So:

1. Don't bother checking for valid variable names, always quote. `("%q"):format( str )` exists if you need to generate code, otherwise `t[str]` works for read/write access, including `_G[str]` for access on the globals table.

2. Don't use the global environment for untrusted user data. There's no big difference between `USERVARS["name"]` and `_G["name"]` or just `name` in generated code, but if the user (accidentally or intentionally) overwrites `pairs` or `math`, you'll likely get a crash (or worse). At best, it's just a confused user and a support ticket, at worst a crash could cause actual damage or it might create an exploitable situation leading to other problems.

With that approach:

- any string is valid and safe as a variable name (tho you should probably set a length limit of a few kilobytes at most); and while you're free to restrict for readability, you don't have to
- read/write `USERVARS[str]` to get/set the value
- for serialization, `("USERVARS[%q]"):format( str )` is the variable name

That should be reasonably safe, and also simpler than dynamically checking if a name is probably ok…

-- nobody