lua-users home
lua-l archive

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


On 04/02/12 00:53, Mateusz Czaplinski wrote:
> Now, on a somewhat related note, I'll let myself to point out that you
> might want to be careful with regards to sandboxing Lua. (Disclaimer
> again: I have never actually tried/needed to do that myself.) At first
> sight, that seems trivial, and I've seen pretty bold opinions here on
> how to do that "quickly and easily" (specially, the lua-wiki page
> about sandboxing is very optimistic). But with safety things can be
> tricky, and there are people here who can point you to some
> non-obvious dangers, and hopefully to some solutions. 

On our servers, we won't shell out, we will probably use the Lua
extension for PHP that I wrote for this purpose:

http://svn.wikimedia.org/viewvc/mediawiki/trunk/php/luasandbox/

> My personal
> landmarks in this topic are currently:
> 
>   * by Peter Cawley, http://article.gmane.org/gmane.comp.lang.lua.general/77422

load() is not exposed to user code. And I read the implementation of
lua_load() in 5.1 and used it to write loadString() and loadBinary()
functions exposed to PHP which can't implicitly switch to the other
kind of input. They detect the magic number that Lua uses to mark
bytecode, and give an error if you try to give it the wrong format.

<http://svn.wikimedia.org/viewvc/mediawiki/trunk/php/luasandbox/luasandbox.c?revision=110236&view=markup#l701>

>   * by Mike Pall,
> http://article.gmane.org/gmane.comp.lang.lua.general/76283 (and more
> in this thread)
>   * by Luiz Henrique de Figueiredo,
> http://lua-users.org/lists/lua-l/2006-06/msg00133.html

To limit CPU usage, I used setitimer() to generate a signal, and in
response to that signal, a hook function is set which aborts the
sandbox execution with luaL_error(). I set a second "emergency" timer,
intended to abort script execution if the hook function never runs. I
use a global variable toggled at the Lua/PHP transition to detect
whether Lua or PHP code is running, and destroy either the sandbox or
the PHP request accordingly.

Calling longjmp() from a signal handler is a last resort and has lots
of bugs associated with it, but that's how PHP implements its time
limits, so we've explored some of the issues already.

Memory limits are implemented with a custom allocator function. In the
non-JIT case, memory is allocated from PHP's per-request pool, so it's
also limited by PHP. In the JIT case, this wasn't possible due to the
problem with 64-bit pointer widths. LuaJIT throws an error from
lua_newstate() if you supply a custom allocator, but luckily
lua_setallocf() was unprotected, so I was able to work around it.

There's a security feature in my PHP extension which you might not
have thought of: I rewrote tostring() in order to avoid disclosing
memory locations. Disclosing memory locations of Lua objects defeats
ASLR and makes heap overflow vulnerabilities much easier to exploit.

-- Tim Starling