如何通过C API在自己的环境中执行不信任的LUA文件[英] How to execute an untrusted Lua file in its own environment from the C API

本文是小编为大家收集整理的关于如何通过C API在自己的环境中执行不信任的LUA文件的处理方法,想解了如何通过C API在自己的环境中执行不信任的LUA文件的问题怎么解决?如何通过C API在自己的环境中执行不信任的LUA文件问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我想通过调用 lua_setfenv()

推荐答案

请参阅Lua用户的 sandboxing 的讨论脚本安全的主题.这种事情有许多微妙的,不是那么微妙的问题.可以做到这一点,但是保护诸如for i=1,1e39 do end之类的代码不仅需要限制用于沙箱的功能.

一般技术是为具有允许功能的白名单的沙箱创建一个功能环境.在某些情况下,该列表甚至可能是空的,但是让用户可以访问pairs(),例如,几乎肯定是无害的. Sandbox页面的系统函数列表通过其安全性分解为构建此类白名单的方便参考.

然后,您使用lua_setfenv()将功能环境应用于用户的脚本,并适当地使用lua_loadfile()或lua_loadstring()加载(但尚未执行).附有环境,您可以使用lua_pcall()和朋友执行它.在执行之前,有些人实际上已经扫描了已加载的字节码以进行他们不想允许的操作.可以用来绝对禁止循环或写入全局变量.

另一个注意事项是,加载函数通常会加载预编译字节模式或LUA文本.事实证明,如果您从不允许预编译字节码,则可以更安全,因为已经确定了多种使VM不当行为的方法,所有方法都取决于手工制作无效的字节码.由于字节码文件以一个定义明确的字节序列开头,这不是普通的ASCII文本,因此您需要做的就是将脚本读取到字符串缓冲区中,测试标记的缺失,并且仅将其传递给lua_loadstring()如果不是字节.

lua-l邮寄列表上这种事情的几年,因此搜索也可能会有所帮助.

其他推荐答案

顺便说一句,这就是我最终所做的:

/* Loads, compiles and executes an unstrusted file. */
bool Lua::RunUntrustedFile(const string& path)
{
    if(luaL_loadfile(mState, path.c_str()))
    {
        ErrorLog(lua_tostring(mState, 1));
        Pop(1);
        return false;
    }

    Lua::SetMaximumInstructions(100000000);
    lua_newtable(mState);
    lua_setglobal(mState, "upload");
    ASSERT(Lua::GetStackSize() == 1);
    lua_getglobal(mState, "upload");
    ASSERT_ALWAYS(lua_setfenv(mState, 1) != 0);
    ASSERT(Lua::GetStackSize() == 1);

    if(lua_pcall(mState, 0, 0, 0))
    {
        Lua::ClearMaximumInstructions();
        ErrorLog(lua_tostring(mState, -1));
        Pop(1);
        return false;
    }

    ASSERT(Lua::GetStackSize() == 0);
    Lua::ClearMaximumInstructions();

    return true;
}

"支持"功能:

static void Pop(int elements = 1) { lua_pop(mState, elements); }

/* Sets a maximum number of instructions before throwing an error */
static void SetMaximumInstructions(int count) {
    lua_sethook(mState, &Lua::MaximumInstructionsReached, LUA_MASKCOUNT, count);
}
static void ClearMaximumInstructions() {
    lua_sethook(mState, &Lua::MaximumInstructionsReached, 0, 0);
}

static void MaximumInstructionsReached(lua_State *, lua_Debug *)
{
    Error("The maximum number of instructions has been reached");
}

static int GetStackSize() { return lua_gettop(mState); }

其他推荐答案

luaL_loadfile()将加载块,然后调用lua_setfenv()设置环境表,然后调用lua_pcall()以执行块.请参阅Maygarden法官在在.lua的功能使用手柄?

本文地址:https://www.itbaoku.cn/post/359339.html