Using GEP to jail untrusted code?

104 views
Skip to first unread message

askth...@googlemail.com

unread,
Feb 10, 2009, 2:00:08 AM2/10/09
to lua-alchemy-dev
Hey there!

Thanks so much for your work on lua-alchemy!

I was looking forward to Global Environment Protection and a few days
ago the wiki page appeared, but I’m unsure whether it does what I’m
looking for. The main reason I’m interested in lua-alchemy is because
I’m working on a site that let’s users write programs utilizing our
APIs. So what I need is to jail the Lua script from accessing anything
it’s not supposed to. (Cookies for instance.)

Can you please give me some pointers to what the right approach would
be, whether lua-alchemy supports this and if not, where I should start
looking to add such a feature?

Cheers,

Stefan

Alexander Gladysh

unread,
Feb 10, 2009, 2:38:18 AM2/10/09
to lua-alc...@googlegroups.com, askth...@googlemail.com
Hey, Stefan!

> Thanks so much for your work on lua-alchemy!

Thank you for your interest to our project!

> I was looking forward to Global Environment Protection and a few days
> ago the wiki page appeared, but I'm unsure whether it does what I'm
> looking for. The main reason I'm interested in lua-alchemy is because
> I'm working on a site that let's users write programs utilizing our
> APIs. So what I need is to jail the Lua script from accessing anything
> it's not supposed to. (Cookies for instance.)

> Can you please give me some pointers to what the right approach would
> be, whether lua-alchemy supports this and if not, where I should start
> looking to add such a feature?

What you want to achieve can be done. However, GEP is of little use here.

The Global Environment Protection feature is to protect code from
accessing undeclared global variables. If global variable is already
there, GEP does not do anything to prevent access to it.

What you need is to limit API available to users. In Lua this is often
called Sandboxing.

The key technique is to execute user's code in the separate,
sandboxed, environment:

local my_api =
{
some_api_function = function()
print("Hello, world!")
end;
}

local run_in_sandbox = function(users_code, my_api)
local res, err = loadstring(users_code)
if res then
setfenv(fn, my_api)
return pcall(fn)
end
end

run_in_sandbox([[some_api_function()]], my_api)

A few hints:

1. Never run user's bytecode, always compile from the source. You want
to replace loadstring, loadfile and load (also dofile) with thin
wrappers to do appropriate checks.

2. Provide to user's code only API which you allow it to use. Do not
provide anything else. You may find the list of sandbox-safe Core Lua
API functions in the wiki (see link below).

3. Lua Alchemy API is *not* sandbox-safe. Write with Lua Alchemy API
your own API that does only what you need to allow user to do, and
expose it.

4. You need to decide if you want to limit memory and CPU usage by
user's code. This is a bit harder to do, but quite possible. It may
require some work with Lua C API though. I'm actually interested in
adding built-in sandboxing support to Lua Alchemy, so I may help you
here.

You may find more hints on sandboxing at Lua wiki:
http://lua-users.org/wiki/SandBoxes

If you have further questions, please do not hesitate to ask them on
the list -- I'll be glad to help.

HTH,
Alexander.

askth...@googlemail.com

unread,
Feb 10, 2009, 6:56:22 AM2/10/09
to lua-alchemy-dev
Hey Alexander!

Thanks for the quick response!

> The key technique is to execute user's code in the separate,
> sandboxed, environment:
>
> [code example]

Just what I needed, thanks! I'm a total beginner on Lua, so I wasn't
aware that it supports sandboxing on it's own. That wiki page is
extremely helpful and a quick google unveiled tons of resources on Lua
sandboxes. Very cool stuff.


> 4. You need to decide if you want to limit memory and CPU usage by
> user's code. This is a bit harder to do, but quite possible. It may
> require some work with Lua C API though.

Might scriptTimeLimit (http://tinyurl.com/d638mx) help here? Obviously
it depends on the implementation details, but Alchemy and therefore
Lua code is in principle still subject to the AVM2 execution time
limit, no? That's unless flyield() is used of course in which case
control would be returned anyway, so it would be possible to have
another timer running, checking the script's runtime and - if
necessary - killing it. Such a timer could also check memory usage
simply by checking the length of the Alchemy ByteArray.

> I'm actually interested in adding built-in sandboxing support to
> Lua Alchemy, so I may help you here.

Absolutely, if I can help with testing let me know!

Cheers,

Stefan

Alexander Gladysh

unread,
Feb 10, 2009, 8:02:06 AM2/10/09
to lua-alc...@googlegroups.com, askth...@googlemail.com
> The key technique is to execute user's code in the separate,
> sandboxed, environment:
>
> local my_api =
> {
> some_api_function = function()
> print("Hello, world!")
> end;
> }
>
> local run_in_sandbox = function(users_code, my_api)
> local res, err = loadstring(users_code)
> if res then
> setfenv(fn, my_api)
> return pcall(fn)
> end
> end
>
> run_in_sandbox([[some_api_function()]], my_api)

One thin moment here. In this code my_api environment table is shared
between calls of user code. It may be not exactly what you want.

Simplest solution is to recreate it each time:

local make_my_api = function()
return


{
some_api_function = function()
print("Hello, world!")
end;
}
end

local run_in_sandbox = function(users_code, my_api)
local res, err = loadstring(users_code)
if res then
setfenv(fn, my_api)
return pcall(fn)
end
end

run_in_sandbox([[some_api_function()]], make_my_api())

HTH,
Alexander.

Alexander Gladysh

unread,
Feb 10, 2009, 8:15:50 AM2/10/09
to lua-alc...@googlegroups.com
> Thanks for the quick response!

You're welcome!

>> 4. You need to decide if you want to limit memory and CPU usage by
>> user's code. This is a bit harder to do, but quite possible. It may
>> require some work with Lua C API though.

> Might scriptTimeLimit (http://tinyurl.com/d638mx) help here? Obviously
> it depends on the implementation details, but Alchemy and therefore
> Lua code is in principle still subject to the AVM2 execution time
> limit, no?

Looks good. I do not see any reason why this shouldn't work.

> That's unless flyield() is used of course in which case
> control would be returned anyway, so it would be possible to have
> another timer running, checking the script's runtime and - if
> necessary - killing it.

Just do not expose flyield() to user.

> Such a timer could also check memory usage
> simply by checking the length of the Alchemy ByteArray.

You may also check amount of memory, allocated by Lua GC:

http://www.lua.org/manual/5.1/manual.html#pdf-collectgarbage
http://www.lua.org/manual/5.1/manual.html#lua_gc

Alchemy's ByteArray should be more safe though -- since user might
somehow get access to some memory-heavy lightuserdata (a pointer,
which counts as pointer size by GC, but points to huge foreign object
in memory).

>> I'm actually interested in adding built-in sandboxing support to
>> Lua Alchemy, so I may help you here.

> Absolutely, if I can help with testing let me know!

Thanks. Sandboxing is actually an "on-demand" feature for Lua Alchemy,
so it is not a very high priority task (not a 0.3 one anyway). Sorry
for not being clear.

However, like I said, I'm interested in adding this feature, and if
you'll realize that to get it working you'll need any feature
implemented inside Lua Alchemy itself (like, for example, exposing
lua_gc to AS3 code), feel free to ask.

In return, we're open for contributions Lua Alchemy usage experience
and/or actual code. ;-)

HTH,
Alexander.

Stefan Thomas

unread,
Feb 10, 2009, 10:36:26 AM2/10/09
to lua-alchemy-dev


> One thin moment here. In this code my_api environment table is shared
> between calls of user code. It may be not exactly what you want.

Shared environments are fine in my case (every script has it's own
Flash Player session), but I bet somebody will find this thread who
gets some use out of this variation.

> Just do not expose flyield() to user.

I meant if it's not used by lua-alchemy in the course of executing
code. (If that is somehow a stupid notion, please forget I ever
mentioned it. :)

> Thanks. Sandboxing is actually an "on-demand" feature for Lua
> Alchemy, so it is not a very high priority task (not a 0.3 one
> anyway). Sorry for not being clear.

Perhaps I'm overlooking something, but I don't really see any need for
sandboxing features on the lua-alchemy level. As I pointed out and you
confirmed, resource limitations easily be enforced by AS3 and Lua
itself has solid, mature sandboxing. So adding any feature in between
would probably be for convenience only, perhaps even convenience at
the expense of stability/security. Or what kind of features do you
have in mind?

> In return, we're open for contributions Lua Alchemy usage
> experience and/or actual code. ;-)

Absolutely! The current version of the software uses a very basic
custom scripting language, so right now I'm evaluating various
options. Lua-alchemy is one, AS3eval (http://eval.hurlant.com/) is
another. And finally we could simply stick with the custom language
and extend it. Lua is looking very good right now, so if we do go with
it, you'll definitely see me posting some code as I move along (which
may be quite slowly, aiming for an open beta in June 09).

Cheers,

Stefan :-)

Alexander Gladysh

unread,
Feb 10, 2009, 3:48:44 PM2/10/09
to lua-alc...@googlegroups.com
>> Just do not expose flyield() to user.

> I meant if it's not used by lua-alchemy in the course of executing
> code. (If that is somehow a stupid notion, please forget I ever
> mentioned it. :)

No, it is not a stupid notion. In fact, you're right, we planned to
use flyield() in as3.filegetcontents(). There are some problems with
that in so far:

http://tinyurl.com/bns7ey
http://tinyurl.com/c4m4dt

>> Thanks. Sandboxing is actually an "on-demand" feature for Lua
>> Alchemy, so it is not a very high priority task (not a 0.3 one
>> anyway). Sorry for not being clear.

> Perhaps I'm overlooking something, but I don't really see any need for
> sandboxing features on the lua-alchemy level. As I pointed out and you
> confirmed, resource limitations easily be enforced by AS3 and Lua
> itself has solid, mature sandboxing. So adding any feature in between
> would probably be for convenience only, perhaps even convenience at
> the expense of stability/security. Or what kind of features do you
> have in mind?

Lua Alchemy, as it is now, does not provide access to lua_State to AS3
user code. That means that all almost all you want to do with Lua, you
have to do in plain Lua. It is likely that some things you'll need for
sandboxing are better be done with Lua C API. If you need any such
thing -- feature requests are welcome.

>> In return, we're open for contributions Lua Alchemy usage
>> experience and/or actual code. ;-)

> Absolutely!

Thank you!

> The current version of the software uses a very basic
> custom scripting language, so right now I'm evaluating various
> options. Lua-alchemy is one, AS3eval (http://eval.hurlant.com/) is
> another. And finally we could simply stick with the custom language
> and extend it. Lua is looking very good right now, so if we do go with
> it, you'll definitely see me posting some code as I move along (which
> may be quite slowly, aiming for an open beta in June 09).

My opinion is highly biased, but I'll recommend you to use Lua.

Lua is mature, brilliantly designed, blazingly fast dynamic language.
I still have to see a better designed dynamic language that would be
so well balanced while being easy to use for both "system" and
business logic levels of programming.

Looking forward for any feedback on Lua Alchemy experience,
Alexander.

Reply all
Reply to author
Forward
0 new messages