Recently on www.ubercomp.com, a post was made regarding how the Redis sandbox was broken for Debian and Debian derived Linux distributions. Also, it was mentioned that the Upstream Redis was not affected, and it is known as a Debian vulnerability. It was assigned a CVE ID of CVE-2022-0543. Ubuntu has released USN-5316-1 for the same.
Overview
Redis is a popular caching service that may be used as a message broker. Clients transmit commands to a Redis server over a socket, and the server responds by changing its state (i.e., its in-memory structures). Redis scripting engine is the Lua programming language, which can be accessed using the eval command. The Lua engine should be sandboxed, which means that clients should be able to communicate with Redis APIs from Lua but not be able to run arbitrary code on the machine where Redis is operating.
Background
In January 2022, a study on Redis was done to find interesting things about cloud providers of standalone Redis services might do, which can lead to cross-account vulnerabilities. Some examples of such attacks are
The general structure of the attack is
Usually, the container can be escaped trivially. The fact that the orchestrator/metadata service accepts commands is definitely a vulnerability, but a fairly prevalent one. The word is out that it’s possible to talk to orchestrators/metadata services from less privileged contexts, so maybe that will get fixed over time. But for now, cool bounties can be made by researchers.
The Proof of Concept (reproduced from www.ubercomp.com)
On an x86-64 machine, one can do:
eval ‘local os_l = package.loadlib(“/usr/lib/x86_64-linux-gnu/liblua5.1.so”, “luaopen_os”); local os = os_l(); os.execute(“touch /tmp/redis_poc”); return 0’
For other architectures, the path to loadlib must be adjusted.
How It Happened
Initially, a general vulnerability was found, but when trying the PoC on different distros or code built by the Engineer did not work. The Upstream Redis statically links Lua, and the functions luaopen_package and luaopen_os are not used by Redis and are not even present in the binary. The Redis upstream also includes and initializes the Lua-bitop and Lua-cjson libraries, which are not part of standard Lua, and the initialization of upstream Redis looks like this:
void luaLoadLibraries(lua_State *lua) {
luaLoadLib(lua, “”, luaopen_base);
luaLoadLib(lua, LUA_TABLIBNAME, luaopen_table);
luaLoadLib(lua, LUA_STRLIBNAME, luaopen_string);
luaLoadLib(lua, LUA_MATHLIBNAME, luaopen_math);
luaLoadLib(lua, LUA_DBLIBNAME, luaopen_debug);
luaLoadLib(lua, “cjson”, luaopen_cjson);
luaLoadLib(lua, “struct”, luaopen_struct);
luaLoadLib(lua, “cmsgpack”, luaopen_cmsgpack);
luaLoadLib(lua, “bit”, luaopen_bit);
#if 0 /* Stuff that we don’t load currently, for sandboxing concerns. */
luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);
luaLoadLib(lua, LUA_OSLIBNAME, luaopen_os);
#endif
On Debian, Redis dynamically loads Lua, and their own packages Lua-bitop and Lua-cjson are loaded when the Lua interpreter initialized itself. When the interpreter initialization was performed the module requires Lua variables present in the global environment on upstream Lua, but not on Redis’ Lua, and would also enable this same attack, which is cleared out, but the package variable was not. It was done through the debian/rules file, which generates a debian/lua_libs_debian.c file, which is included right after the #endif directive shown above.
Who is Affected
Users running Redis on Debian, Ubuntu, and possibly other Debian-based distros should ensure that their system is updated.
Looking for a Solution:
Surprisingly, the Engineer informed about this attack to Debian and Ubuntu separately. The expectation is that Ubuntu would either automatically pick the fix up or that there would be a manual process wherein someone at Canonical would take a look at all Debian security announcements and check whether they apply to Ubuntu as well.
Source: https://www.ubercomp.com/posts/2022-01-20_redis_on_debian_rce