lua-users home
lua-l archive

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


On Nov 10, 2007 4:38 AM, Patrick Donnelly <batrick.donnelly@gmail.com> wrote:
> I just tried using this:
>
> secureenviron = {
>   getfenv = function(...)
>     return _G.getfenv(...)
>   end,
>   --... other lua functions
> }
> for _,v in pairs(secureenviron) do
>   if type(v) == "function" then setfenv(v, secureenviron) end
> end
>
> This protects against: getfenv(getfenv) to get ahold of the global
> table, I have no idea how to prevent climbing the stack levels to get
> at the global environment other than raising an error. Doing simple
> checks to see if the table returned by getfenv() is the global table
> seems prone to errors (and attack).

The basic principle I use in cladbot's sandbox (which is a nice
limited case because the environments are one-shot and generated on
the fly) is to replace the global getfenv and setfenv functions, and
return the "clean" environment, unless the user has set a function
environment on the argument being passed into getfenv().  Since I
control setting the environment with a custom setfenv(), it makes this
rather trivial.

In short, when you need a "Clean environment":
1. Create a new table (cleanEnv)
2. Do a shallow copy of _G, changing the reference to _G to cleanEnv.
3. Define a new setfenv() that calls the original, after tracking
which function has been tacked with which environment table, so you
can write...
4. A new getfenv() function which returns cleanEnv by default, and
otherwise does a lookup to see which stack level you need to return.
This is the tricky part, but honestly in most cases this part of
things can be fudged if necessary.

I've found this to be rather successful, although by no means
impervious to attacks.  Actually in the current bot I have setfenv()
disabled because I hadn't had a reason to implement the new setfenv()
and getfenv() is hardwired to return the clean environment each time.
Previous (and later) iterations used the above method.

Rather than "protect" the global environment.. which as you state is
rather prone to attacks, simply replace it with a new one for each
sandbox you need to create.

- Jim