如何在Lua中封装IO函数以防止用户离开X目录

你怎样在 Lua 中包装 IO(输入/输出)函数来防止有人离开顶级目录?

你将它们放置在"MyDoc"目录中,它们可以完全访问MyDoc子目录中的所有内容,但不能例如回到C驱动器或其他任何地方。

点赞
用户3076936
用户3076936

打开 liolib.c 文件,进入下面这三个函数:

static void opencheck (lua_State *L, const char *fname, const char *mode) {
  LStream *p = newfile(L);
  p->f = fopen(fname, mode);
  if (p->f == NULL)
    luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
}

static int io_open (lua_State *L) {
  const char *filename = luaL_checkstring(L, 1);
  const char *mode = luaL_optstring(L, 2, "r");
  LStream *p = newfile(L);
  const char *md = mode;  /* to traverse/check mode */
  luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode");
  p->f = fopen(filename, mode);
  return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
}

static int io_popen (lua_State *L) {
  const char *filename = luaL_checkstring(L, 1);
  const char *mode = luaL_optstring(L, 2, "r");
  LStream *p = newprefile(L);
  p->f = lua_popen(L, filename, mode);
  p->closef = &io_pclose;
  return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
}

这些是您想要编辑的函数。

第一个函数将文件名作为参数 fname 接收,第二个和第三个 将其作为局部变量 filename 从 lua 栈中弹出。

现在你所需要做的就是:

1)获取自己的进程路径

2)规范给定的文件路径

3)比较它们,使它们在最后一个斜杠之前是相同的

4)如果它们不相同,则在 opencheck 中使用 luaL_error(L,"access denied to %s", fname);,其他两个函数中使用 return luaL_fileresult(L,0,filename);

2013-12-21 08:29:53
用户869951
用户869951

假设你将用户环境设置为沙箱,所以他们不能使用内置的“require”、“dofile”或“setatable”函数?

基本上,你必须限制他们能够调用的函数,只允许你想要的函数,并且创建自己想要控制的任何内容的版本。有几种方法可以做到这一点,它们各有优缺点,没有一个是不可打破的,你所能做的就是提高打破“监狱”所需的经验、努力和时间的门槛。

这意味着你必须在 C API 层面工作,但我并不建议修改源代码,除非你非常熟悉它并且可以轻松确定你的修改不容易被打破。通过停留在 C API 层面,至少其他 Lua 用户可以帮助验证沙箱的可靠性。

你必须想出一种方法,使你的代码可以调用 Lua 的内置函数,同时又不允许用户调用内置函数。我相信你可以在 lua 注册表中存储表,只有 C 代码可以查看。这已经有一段时间了。或者,如果你不把 getmetable 放在用户环境中,那么你就可以通过 metatable 调用内置函数,但用户无法访问它们。

例如,在 C 中:

  • 你加载像 io 模块这样的内置模块,并在 (元)表中保存你要包装的函数(如 open);
  • 从 _G 中删除 io 内置表,这样用户只能访问你创建的版本;你已经保存了稍后需要的函数
  • 创建一个名为 io 的全局表,并将其元表设置为步骤 1 中创建的表,这样它只定义你想要给予访问权限的函数,如名为“open”的函数。
  • 在该函数中,你可以在调用保存的内置函数之前做任何必要的过滤。

细节将产生很大的差异,如果你使用的是 Lua 5.1 还是 5.2,实现方式也会有所不同,但是网上有几篇关于在 Lua 中沙箱的好文章(很抱歉没有时间找),看看并想出一些方法,然后可能在 Lua 用户邮件列表或 SO 上发布一下,寻求专业人士的建议。;)

2013-12-21 13:41:56