mirror of
https://github.com/kikito/lua-sandbox.git
synced 2024-12-18 03:04:20 +00:00
feat(sandbox) block bytecode when possible
This commit is contained in:
parent
485a14697c
commit
d4e8634ccd
35
README.md
35
README.md
@ -9,6 +9,16 @@ It's possible to provide extra functions via the `options.env` parameter.
|
|||||||
|
|
||||||
Infinite loops are prevented via the `debug` library.
|
Infinite loops are prevented via the `debug` library.
|
||||||
|
|
||||||
|
Supported Lua versions:
|
||||||
|
======================
|
||||||
|
|
||||||
|
All the features of sandbox.lua work in the following Lua environments:
|
||||||
|
|
||||||
|
|
||||||
|
* PUC-Rio Lua 5.1 **allows execution of bytecode**, which is a huge limitation (see the bytecode section below)
|
||||||
|
* PUC-Rio Lua 5.2, 5.3, 5.4 have total support.
|
||||||
|
* LuaJIT is not protected against infinite loops (see the notes in `options.quota` below)
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
@ -51,6 +61,29 @@ local sf = sandbox.protect([[
|
|||||||
sf() -- error: quota exceeded
|
sf() -- error: quota exceeded
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Bytecode
|
||||||
|
|
||||||
|
It is possible to exit a sandbox using Lua bytecode. References:
|
||||||
|
|
||||||
|
* http://apocrypha.numin.it/talks/lua_bytecode_exploitation.pdf
|
||||||
|
* https://github.com/erezto/lua-sandbox-escape
|
||||||
|
* https://gist.github.com/corsix/6575486
|
||||||
|
|
||||||
|
Because of this, the sandbox deactivates bytecode in all the versions of Lua where it is possible:
|
||||||
|
|
||||||
|
* PUC-Rio Lua 5.2, 5.3, 5.4
|
||||||
|
* LuaJIT
|
||||||
|
|
||||||
|
In other words, _all except PUC-Rio Lua 5.1_.
|
||||||
|
|
||||||
|
** The sandbox can be exploited in PUC-Rio Lua 5.1 via bytecode **
|
||||||
|
|
||||||
|
The only reason we keep Lua 5.1 in the list of supported versions of Lua is because
|
||||||
|
sandboxing can help against users attempting to delete a file by mistake. _It does not provide
|
||||||
|
protection against malicious users_.
|
||||||
|
|
||||||
|
As a result we _strongly recommend updating to a more recent version when possible_.
|
||||||
|
|
||||||
### options.quota
|
### options.quota
|
||||||
|
|
||||||
`sandbox.lua` prevents infinite loops from halting the program by hooking the `debug` library to the sandboxed function, and "counting instructions". When
|
`sandbox.lua` prevents infinite loops from halting the program by hooking the `debug` library to the sandboxed function, and "counting instructions". When
|
||||||
@ -95,7 +128,7 @@ recommended to discard it after use.
|
|||||||
|
|
||||||
### sandbox.run
|
### sandbox.run
|
||||||
|
|
||||||
`sandbox.run(code)` sanboxes and executes `code` in a single line. `code` must be a string with Lua code inside.
|
`sandbox.run(code)` sandboxes and executes `code` in a single line. `code` must be a string with Lua code inside.
|
||||||
|
|
||||||
You can pass `options` param, and it will work like in `sandbox.protect`.
|
You can pass `options` param, and it will work like in `sandbox.protect`.
|
||||||
|
|
||||||
|
13
sandbox.lua
13
sandbox.lua
@ -33,9 +33,9 @@ local sandbox = {
|
|||||||
local quota_supported = type(_G.jit) == "nil"
|
local quota_supported = type(_G.jit) == "nil"
|
||||||
sandbox.quota_supported = quota_supported
|
sandbox.quota_supported = quota_supported
|
||||||
|
|
||||||
-- PUC-Rio Lua 5.1 does not support deactivation of binary code
|
-- PUC-Rio Lua 5.1 does not support deactivation of bytecode
|
||||||
local mode_supported = _ENV or type(_G.jit) == "table"
|
local bytecode_blocked = _ENV or type(_G.jit) == "table"
|
||||||
sandbox.mode_supported = mode_supported
|
sandbox.bytecode_blocked = bytecode_blocked
|
||||||
|
|
||||||
-- The base environment is merged with the given env option (or an empty table, if no env provided)
|
-- The base environment is merged with the given env option (or an empty table, if no env provided)
|
||||||
--
|
--
|
||||||
@ -143,12 +143,9 @@ function sandbox.protect(code, options)
|
|||||||
|
|
||||||
|
|
||||||
local f
|
local f
|
||||||
if mode_supported then
|
if bytecode_blocked then
|
||||||
f = assert(load(code, nil, options.mode, env))
|
f = assert(load(code, nil, 't', env))
|
||||||
else
|
else
|
||||||
if options.mode then
|
|
||||||
error("options.mode is not supported on this environment (usually PUC-Rio Lua 5.1). Please unset options.mode")
|
|
||||||
end
|
|
||||||
f = assert(loadstring(code))
|
f = assert(loadstring(code))
|
||||||
setfenv(f, env)
|
setfenv(f, env)
|
||||||
end
|
end
|
||||||
|
@ -9,19 +9,15 @@ describe('sandbox.run', function()
|
|||||||
assert.equal(r, 'hello')
|
assert.equal(r, 'hello')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('can run bytecode strings by default', function()
|
if sandbox.bytecode_blocked then
|
||||||
|
it('rejects bytecode', function()
|
||||||
local fn = function() end
|
local fn = function() end
|
||||||
assert.has_no.error(function() sandbox.run(string.dump(fn)) end)
|
assert.error(function() sandbox.run(string.dump(fn)) end)
|
||||||
end)
|
|
||||||
|
|
||||||
if sandbox.mode_supported then
|
|
||||||
it('can\'t run bytecode strings if given a \'t\' mode option', function()
|
|
||||||
local fn = function() end
|
|
||||||
assert.error(function() sandbox.run(string.dump(fn), { mode = 't' }) end)
|
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
it('throws an error if the mode option is used', function()
|
it('accepts bytecode (PUC Rio 5.1)', function()
|
||||||
assert.error(function() sandbox.run("", { mode = 't' }) end)
|
local fn = function() end
|
||||||
|
assert.has.no.error(function() sandbox.run(string.dump(fn)) end)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user