Programing

보안 Lua 샌드 박스를 어떻게 만들 수 있습니까?

crosscheck 2020. 10. 22. 07:42
반응형

보안 Lua 샌드 박스를 어떻게 만들 수 있습니까?


따라서 Lua는 내 응용 프로그램 내에서 보안 "사용자 스크립트"를 구현하는 데 이상적입니다.

그러나 lua를 포함하는 대부분의 예는 "io"및 "package"를 포함한 모든 표준 라이브러리를로드하는 것을 포함하는 것 같습니다.

따라서 인터프리터에서 이러한 라이브러리를 제외 할 수 있지만 기본 라이브러리에도 파일 시스템에 액세스하는 "dofile"및 "loadfile"함수가 포함되어 있습니다.

"ipairs"기능과 같은 기본적인 기능조차없는 인터프리터로 끝나지 않고 이와 같은 안전하지 않은 기능을 제거 / 차단하려면 어떻게해야합니까?


setfenv () 를 통해 신뢰할 수없는 코드를 실행하는 기능 환경을 설정할 수 있습니다 . 다음은 개요입니다.

local env = {ipairs}
setfenv(user_script, env)
pcall(user_script)

user_script함수는 환경에있는 항목에만 액세스 할 수 있습니다. 따라서 신뢰할 수없는 코드가 액세스 할 수 있도록 할 함수를 명시 적으로 추가 할 수 있습니다 (화이트리스트). 이 경우 사용자 스크립트는 액세스가 ipairs아무것 (그러나 dofile, loadfile등).

lua 샌드 박스 에 대한 예제와 자세한 내용 Lua Sandboxes참조하십시오 .


다음은 Lua 5.2 용 솔루션입니다 (5.1에서도 작동하는 샘플 환경 포함).

-- save a pointer to globals that would be unreachable in sandbox
local e=_ENV

-- sample sandbox environment
sandbox_env = {
  ipairs = ipairs,
  next = next,
  pairs = pairs,
  pcall = pcall,
  tonumber = tonumber,
  tostring = tostring,
  type = type,
  unpack = unpack,
  coroutine = { create = coroutine.create, resume = coroutine.resume, 
      running = coroutine.running, status = coroutine.status, 
      wrap = coroutine.wrap },
  string = { byte = string.byte, char = string.char, find = string.find, 
      format = string.format, gmatch = string.gmatch, gsub = string.gsub, 
      len = string.len, lower = string.lower, match = string.match, 
      rep = string.rep, reverse = string.reverse, sub = string.sub, 
      upper = string.upper },
  table = { insert = table.insert, maxn = table.maxn, remove = table.remove, 
      sort = table.sort },
  math = { abs = math.abs, acos = math.acos, asin = math.asin, 
      atan = math.atan, atan2 = math.atan2, ceil = math.ceil, cos = math.cos, 
      cosh = math.cosh, deg = math.deg, exp = math.exp, floor = math.floor, 
      fmod = math.fmod, frexp = math.frexp, huge = math.huge, 
      ldexp = math.ldexp, log = math.log, log10 = math.log10, max = math.max, 
      min = math.min, modf = math.modf, pi = math.pi, pow = math.pow, 
      rad = math.rad, random = math.random, sin = math.sin, sinh = math.sinh, 
      sqrt = math.sqrt, tan = math.tan, tanh = math.tanh },
  os = { clock = os.clock, difftime = os.difftime, time = os.time },
}

function run_sandbox(sb_env, sb_func, ...)
  local sb_orig_env=_ENV
  if (not sb_func) then return nil end
  _ENV=sb_env
  local sb_ret={e.pcall(sb_func, ...)}
  _ENV=sb_orig_env
  return e.table.unpack(sb_ret)
end

그런 다음이를 사용 my_func하려면 다음과 같이 함수 ( )를 호출합니다 .

pcall_rc, result_or_err_msg = run_sandbox(sandbox_env, my_func, arg1, arg2)

루아 라이브 데모는 A (전문) 샌드 박스가 포함되어 있습니다. 소스는 자유롭게 사용할 수 있습니다.


바람직하지 않은 것을 제거하는 가장 쉬운 방법 중 하나는 먼저 자신이 고안 한 Lua 스크립트를로드하는 것입니다.

load = nil
loadfile = nil
dofile = nil

Alternatively, you can use setfenv to create a restricted environment that you can insert specific safe functions into.

Totally safe sandboxing is a little harder. If you load code from anywhere, be aware that precompiled code can crash Lua. Even completely restricted code can go into an infinite loop and block indefinitely if you don't have system for shutting it down.


You can use the lua_setglobal function provided by the Lua API to set those values in the global namespace to nil which will effectively prevent any user scripts from being able to access them.

lua_pushnil(state_pointer);
lua_setglobal(state_pointer, "io");

lua_pushnil(state_pointer);
lua_setglobal(state_pointer, "loadfile");

...etc...

If you're using Lua 5.1 try this:

blockedThings = {'os', 'debug', 'loadstring', 'loadfile', 'setfenv', 'getfenv'}
scriptName = "user_script.lua"

function InList(list, val) 
    for i=1, #list do if list[i] == val then 
        return true 
    end 
end

local f, msg = loadfile(scriptName)

local env = {}
local envMT = {}
local blockedStorageOverride = {}
envMT.__index = function(tab, key)
    if InList(blockedThings, key) then return blockedStorageOverride[key] end
    return rawget(tab, key) or getfenv(0)[key]
end
envMT.__newindex = function(tab, key, val)
    if InList(blockedThings, key) then
        blockedStorageOverride[key] = val
    else
        rawset(tab, key, val)
    end
end

if not f then
    print("ERROR: " .. msg)
else
    setfenv(f, env)
    local a, b = pcall(f)
    if not a then print("ERROR: " .. b) end
end

You can override (disable) any Lua function you want and also you can use metatables for more control.

참고URL : https://stackoverflow.com/questions/1224708/how-can-i-create-a-secure-lua-sandbox

반응형