Daher scheint Lua ideal für die Implementierung sicherer "Benutzerskripte" in meiner Anwendung zu sein.
Die meisten Beispiele für das Einbetten von Lua scheinen jedoch das Laden aller Standardbibliotheken zu umfassen, einschließlich "io" und "package".
Ich kann diese Bibliotheken also von meinem Interpreter ausschließen, aber selbst die Basisbibliothek enthält die Funktionen "dofile" und "loadfile", die auf das Dateisystem zugreifen.
Wie kann ich unsichere Funktionen wie diese entfernen / blockieren, ohne nur einen Interpreter zu haben, der nicht einmal grundlegende Dinge wie die "ipairs" -Funktion enthält?
local env = {ipairs=ipairs}
. Und wenn Sie dies auf dem interaktiven lua cli ausführen, wickeln Sie das Ganze in einedo ... end
Schleife, damit Sie die lokalen Variablen nicht verlieren.load()
dasenv
Argument verwenden, wassetfenv()
ohnehin eine viel sicherere Alternative ist, da Sie es nicht so leicht vergessen können.Hier ist eine Lösung für Lua 5.2 (einschließlich einer Beispielumgebung, die auch in 5.1 funktionieren würde):
-- 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
Um es dann zu verwenden, würden Sie Ihre Funktion (
my_func
) wie folgt aufrufen :quelle
setfenv
wurde aus 5.2 entfernt: lua.org/work/doc/manual.html#8.2Die Lua Live-Demo enthält eine (spezialisierte) Sandbox. Die Quelle ist frei verfügbar.
quelle
Eine der einfachsten Möglichkeiten, unerwünschte Ereignisse zu beseitigen, besteht darin, zuerst ein Lua-Skript zu laden, das Sie selbst erstellt haben.
load = nil loadfile = nil dofile = nil
Alternativ können Sie
setfenv
eine eingeschränkte Umgebung erstellen, in die Sie bestimmte sichere Funktionen einfügen können.Völlig sicheres Sandboxen ist etwas schwieriger. Wenn Sie Code von überall laden, beachten Sie, dass vorkompilierter Code Lua zum Absturz bringen kann. Selbst vollständig eingeschränkter Code kann in eine Endlosschleife gelangen und unbegrenzt blockieren, wenn Sie kein System zum Herunterfahren haben.
quelle
Mit der
lua_setglobal
von der Lua-API bereitgestellten Funktion können Sie die Werte im globalen Namespace festlegen, aufnil
die effektiv verhindert wird, dass Benutzerskripte auf sie zugreifen können.lua_pushnil(state_pointer); lua_setglobal(state_pointer, "io"); lua_pushnil(state_pointer); lua_setglobal(state_pointer, "loadfile"); ...etc...
quelle
Wenn Sie Lua 5.1 verwenden, versuchen Sie Folgendes:
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
quelle
Sie können jede gewünschte Lua-Funktion überschreiben (deaktivieren) und Metatabellen für mehr Kontrolle verwenden .
quelle