6

lua_setfenv()を呼び出して、信頼できない.luaファイルを独自の環境で実行し、コードに影響を与えないようにします。

ただし、その関数のドキュメントでは、ファイルの実行方法ではなく、関数の呼び出し方法についてのみ説明しています。

現在、私が使用しているファイルを実行するには、次のようにします。

int error = luaL_loadfile(mState, path.c_str()) || lua_pcall(mState, 0, 0, 0);

を使用してCAPIから「dofile」lua関数を呼び出すlua_setfenv必要がありますか、それともより洗練された方法がありますか?

4

3 に答える 3

9

サンドボックスのLuaユーザーのWikiでの説明、およびスクリプトセキュリティのより一般的なトピックを参照してください。この種のものには、微妙な問題とそれほど微妙ではない問題がいくつかあります。それは可能ですが、などのコードから保護for i=1,1e39 do endするには、サンドボックスで使用できる関数を制限するだけでは不十分です。

一般的な手法は、許可された関数のホワイトリストを含むサンドボックスの関数環境を作成することです。場合によっては、そのリストが空になることもありますがpairs()、たとえば、ユーザーにアクセスを許可しても、ほぼ確実に無害です。サンドボックスページには、そのようなホワイトリストを作成するための便利なリファレンスとして、安全性ごとに分類されたシステム機能のリストがあります。

次に、を使用して、または必要に応じlua_setfenv()て、ロードした(ただしまだ実行していない)ユーザーのスクリプトに関数環境を適用します。環境が整っていれば、友達と一緒に実行できます。実行前に、ロードされたバイトコードをスキャンして、許可したくない操作を探している人もいます。これは、ループやグローバル変数への書き込みを完全に禁止するために使用できます。lua_loadfile()lua_loadstring()lua_pcall()

もう1つの注意点は、ロード関数は通常、プリコンパイルされたバイトコードまたはLuaテキストのいずれかをロードすることです。プリコンパイルされたバイトコードを許可しない場合は、VMの誤動作を引き起こすいくつかの方法が特定されており、すべてが無効なバイトコードの手作りに依存しているため、はるかに安全であることがわかります。バイトコードファイルは、プレーンASCIIテキストではない明確に定義されたバイトシーケンスで始まるため、スクリプトを文字列バッファーに読み込み、マーカーがないかどうかをテストし、lua_loadstring()バイトコードでない場合にのみ渡すだけです。 。

Lua-Lメーリングリストでは、この種のことについて何年にもわたってかなりの量の議論が行われているので、そこで検索することも役立つ可能性があります。

于 2010-08-09T23:50:00.990 に答える
5

ちなみに、これは私がやったことです:

/* 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); }
于 2010-11-08T21:25:03.307 に答える
2

luaL_loadfile()チャンクをロードし、を呼び出しlua_setfenv()て環境テーブルを設定し、を呼び出しlua_pcall()てチャンクを実行します。.luaのハンドルを使用してlua関数を呼び出す際にMaygarden裁判官が行った最近の回答を参照してください。

于 2010-08-09T22:17:59.307 に答える