[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: On implementing a functions whitelist for a sandbox
- From: Sean Conner <sean@...>
- Date: Wed, 7 Aug 2019 23:42:17 -0400
It was thus said that the Great Kynn Jones once stated:
> Hi Sean,
>
> Thank you for the detailed explanation.
You're welcome.
> I think that the disconnect here is that I am trying (**really,
> really, really hard**) to implement what Roberto Ierusalimschy
> recommends in chapter 25 (pp. 261-264) of *Programming in Lua*, 4th
> ed., while you (and Coda Highland) are of the opinion (I think) that
> such a strategy is unnecessary. (Apologies if I misunderstood.)
A sandbox is just a limited environment in which you run a program. For
Lua, this can be anything from an environment devoid of *any* prewritten
functions to one with most functions available. Here's a table of Lua
functions that will still be useful, but limits the program from creating
new files, excecuting other programs, or accessing some low level Lua
functions:
newenv =
{
-- include these functions
_VERSION = _VERSION,
assert = assert,
error = error,
ipairs = ipairs,
pairs = ipairs,
next = next,
pcall = pcall,
print = print, -- we can write to stdout
select = select,
tonumber = tonumber,
tostring = tostring,
type = type,
xpcall = xpcall,
-- these modules in their entirety
math = math,
table = table,
string = string,
utf8 = utf8,
-- and these with limited functionality
io =
{
stdin = io.stdin, -- keep this around
stdout = io.stdout, -- and this
stderr = io.stderr, -- and this
},
os =
{
clock = os.clock,
date = os.date,
difftime = os.difftime,
exit = os.exit,
getnev = os.getenv,
setlocale = os.setlocale,
time = os.time,
},
}
newenv._G = newenv
sandboxcode = loadfile(untrustedcode,'t',newenv)
sandboxcode()
Not all functions are included, and certainly, arguments could be made for
including stuff I left out, or excluding stuff I left in. But there's still
a lot of Lua code that could conceivably run with just the functions listed
above. For instance, I left out require(), but it's easy to provide one
that restricts which modules can be used in the sandboxed code:
local okaymods =
{
['lpeg'] = true, -- just a sample of useful modules
['org.conman.env'] = true,
['argparse'] = true,
['math'] = true, -- some code might require these
['table'] = true, -- standard modules, so let them
['string'] = true, -- through even though they're
['utf8'] = true, -- already available "globally"
}
function newenv.require(modname)
if okaymods[modname] then
return require(modname)
elseif modname == 'io' then -- in case some code is trying to
return newenv.io -- be cute ...
elseif modname = 'os' then
return newenv.os
else
error(string.format("Module %s not allowed",modname))
end
end
> In other words, I am not trying to solve any practical problem; I am
> only trying to understand the book's approach to sandboxing. At the
> moment, I think that I still don't understand it (because I cannot put
> it into practice satisfactorily).
I can't help with that, as I do not own the book. But I am familiar with
the concept of sandboxing, as are some other people on this mailing list.
And depending upon your threat model, sandboxing is pretty easy to very darn
difficult.
-spc