Bug#950816: mpv: unintended code execution vulnerability
Control: tags -1 + patch
Control: found -1 mpv/0.29.1-1
FYI, the patch below works for me.
Also, I think the version in stable is also affected. The code differs
slightly so the patch will need a little tweak.
Cheers.
--
>From 937749b545407aa68b1d15ea5e19a6c23d62da42 Mon Sep 17 00:00:00 2001
From: astian <astian@e-nautia.com>
Date: Mon, 11 Feb 2020 21:08:51 +0000
Subject: [PATCH] lua: fix unintended code execution vulnerability
Backport of upstream commit cce7062a8a6b6a3b3666aea3ff86db879cba67b6
("lua: fix highly security relevant arbitrary code execution") to
release 0.32.0.
Note: Before release 0.32.0, it used to be that mpv-related scripts
directories where added to Lua's module-loaders search path. This
behaviour was dropped in 0.32.0 (bc1c024ae032). Later, a similar but
stricter behaviour was introduced (see da38caff9c0b and b86bfc907f9c).
The original commit on which this patch is based depended on the new
behaviour. This backport retains the 0.32.0 behaviour; all it does is
filter out relative paths from "package.path" and "package.cpath" for
all Lua scripts.
---
player/lua.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/player/lua.c b/player/lua.c
index 6423861..172ab4e 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -273,6 +273,36 @@ static int load_scripts(lua_State *L)
return 0;
}
+static void fuck_lua(lua_State *L, const char *search_path)
+{
+ void *tmp = talloc_new(NULL);
+
+ lua_getglobal(L, "package"); // package
+ lua_getfield(L, -1, search_path); // package search_path
+ bstr path = bstr0(lua_tostring(L, -1));
+ char *newpath = talloc_strdup(tmp, "");
+
+ // Unbelievable but true: Lua loads .lua files AND dynamic libraries from
+ // the working directory. This is highly security relevant.
+ // Lua scripts are still supposed to load globally installed libraries, so
+ // try to get by by filtering out any relative paths.
+ while (path.len) {
+ bstr item;
+ bstr_split_tok(path, ";", &item, &path);
+ if (bstr_startswith0(item, "/")) {
+ newpath = talloc_asprintf_append(newpath, "%s%.*s",
+ newpath[0] ? ";" : "",
+ BSTR_P(item));
+ }
+ }
+
+ lua_pushstring(L, newpath); // package search_path newpath
+ lua_setfield(L, -3, search_path); // package search_path
+ lua_pop(L, 2); // -
+
+ talloc_free(tmp);
+}
+
static int run_lua(lua_State *L)
{
struct script_ctx *ctx = lua_touserdata(L, -1);
@@ -326,6 +356,10 @@ static int run_lua(lua_State *L)
assert(lua_gettop(L) == 0);
+ fuck_lua(L, "path");
+ fuck_lua(L, "cpath");
+ assert(lua_gettop(L) == 0);
+
// run this under an error handler that can do backtraces
lua_pushcfunction(L, error_handler); // errf
lua_pushcfunction(L, load_scripts); // errf fn
--
2.25.0
Reply to: