Sybaris Writeup - Proving Grounds
Created October 8, 2026 • Last updated October 8, 2026 • 4 min read
Sybaris combines anonymous FTP write access with Redis’s MODULE LOAD command to get code execution: upload a malicious Redis module over FTP, then load it from its guessed on-disk path. From there, a root cron job with a hijackable LD_LIBRARY_PATH entry gives root.
Reconnaissance
Nmap
Scan all ports.
PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.2 |_ftp-anon: Anonymous FTP login allowed 22/tcp open ssh OpenSSH 7.4 80/tcp open http Apache httpd 2.4.6 (CentOS) PHP/7.3.22 (HTMLy v2.7.5) 6379/tcp open redis Redis key-value store 5.0.9
Explain command
| -p- | Scan all 65535 TCP ports. |
| -sCV | Run the default scripts and probe service versions. |
FTP allows anonymous login and Redis has no authentication. Verify both.
FTP and Redis checks
Confirm anonymous FTP access.
Name: anonymous 230 Login successful. ftp> cd pub ftp> ls (empty, but world-writable)
An empty but writable pub directory. Redis is cleartext, so talk to it directly over telnet.
:0
No keys stored, but anonymous write access to FTP plus an open Redis instance is enough to chain into code execution.
Exploitation
Redis MODULE LOAD via anonymous FTP
Build a Redis module that can run shell commands, using the ExecuteCommand module.
cp ./src/module.so .
Upload the compiled module to the writable FTP directory.
226 Transfer complete.
vsFTPd defaults to /var/ftp/, so the module should have landed at /var/ftp/pub/module.so. Load it into Redis by path.
+OK
The module is loaded and its custom commands are available.
uid=1000(pablo) gid=1000(pablo) groups=1000(pablo)
Catch a full reverse shell with the module’s built-in command.
id uid=1000(pablo) gid=1000(pablo) groups=1000(pablo)
Shell as pablo. local.txt sits in the home directory.
Privilege Escalation
Shared-object hijack via LD_LIBRARY_PATH cron job
A root cron job runs every minute.
LD_LIBRARY_PATH=/usr/lib:/usr/lib64:/usr/local/lib/dev:/usr/local/lib/utils * * * * * root /usr/bin/log-sweeper
The crontab sets a custom LD_LIBRARY_PATH that includes two extra directories. One of them is world-writable and comes first in the search order.
drwxrwxrwx 2 root root 6 /usr/local/lib/dev drwxr-xr-x 2 root root 22 /usr/local/lib/utils -rwxr-xr-x 1 root root 476 /usr/local/lib/utils/utils.so
log-sweeper loads utils.so from that path. Dropping a malicious library of the same name into the writable directory lets it be picked up first.
utils.so => not found libc.so.6 => /lib64/libc.so.6
Generate a malicious shared object as a reverse-shell payload and stage it over the same anonymous FTP write access.
Saved as: utils.so
226 Transfer complete.
Wait for the minutely cron job to run log-sweeper, which loads the planted library ahead of the legitimate one.
id uid=0(root) gid=0(root) groups=0(root)
The hijacked library executes as root when the cron job runs it.
Related
References
-
Redis - MODULE LOADLINK: Redis - MODULE LOAD, redis.io/commands/module-load (opens in new tab)
Redis MODULE LOAD command reference, used to dynamically load a module from a local path.
-
RedisModules-ExecuteCommandREPO: RedisModules-ExecuteCommand, github.com/n0b0dyCN/RedisModules-ExecuteCommand (opens in new tab)
Redis module used to execute shell commands and spawn a reverse shell after MODULE LOAD.