BigIP_backendScan : cookies BigIP et fuite d’information

Aujourd’hui je vous présente un petit outil que j’ai écrit en Python. Il fait suite à diverses expériences autour du pentest web.


Après différentes analyses web, j’ai pu constater que les load-balancer F5 bigIP, que l’on peut très souvent croiser sur des infrastructures de grande taille, avait une façon un peu particulière de gérer leur trafic.

Les cookies des F5 BigIP

Lorsque l’on se rend sur un site web qui est protégé par un load-balancer F5 Big-IP, celui-ci vous assigne un cookie indépendant du site web et propre à BigIP, exemple :

Set-Cookie: BIGipServerp-http-mon-domaine-tld=167903288.20480.0000; path=/

Ce cookie contient une chaîne de caractères à priori anodine, une suite de chiffres. Cependant il a été relevé, depuis plusieurs années maintenant, que cette suite de caractères est l’adresse IP:Port du serveur auquel vous êtes “assigné” à l’intérieur du pool BigIP. En opérant une conversion décimale vers octale, on obtient un résultat beaucoup plus parlant, exemple en Python :

>> import socket
>> import struct
>>> IP = socket.inet_ntoa(struct.pack('!L', 167903288))
>>> socket.inet_ntoa(struct.pack('!L', 167903288))
'10.2.0.56'
>>> socket.inet_ntoa(struct.pack('!L', 20480))
'0.0.80.0'

Nous voyons bien ici une IP et un port “80”.

Dans le cas de BigIP, les octets de l’IP peuvent être dans l’ordre inverse après une conversion, en fonction de l’outil utilisé : exemple “56.0.2.10”.

Ce comportement est logique, même indispensable. Lorsque l’on se rend sur un service web réparti sur plusieurs serveurs différents, il faut que notre session, délivrée par le serveur à la première connexion, soit retrouvée lors de notre navigation. Seulement si nous sommes baladé de serveur en serveur par le load-balancer à chaque fois que l’on fait une nouvelle requête, notre session ne sera jamais retrouvée et la navigation en sera très pertubée.

La solution est donc d’assigner un serveur à chaque session, et cela directement au niveau du load-balancer.

Une solution simpliste serait de procéder au même fonctionnement que le PHPSESSID ou JSESSIONID, le cookie de session est une suite aléatoire de caractères que le client fournit à sa connexion. Le serveur contient une liaison directe entre cette suite de caractères et les informations du client, ainsi l’information n’est jamais en possession du client et encore moins visible par celui-ci.

Mais BigIP ne fonctionne pas comme cela, le cookie contient directement la donnée et cette donnée est, rappelez-vous, le serveur auquel nous sommes “affecté” le temps de notre connexion. De fait, cette information ne peut être qu’une IP, un nom de serveur (ou alias).

En générant plusieurs sessions différentes (par exemple 100), nous aurons des chances d’être affecté à un serveur différent à chaque fois et nous disposerons ainsi d’une liste des serveurs qui constituent le cluster/pool BigIP, un scan des serveurs de backend en somme.

Script python BigIP_backendScan

Le script Python que j’ai écrit permet donc d’automatiser ce scan afin de trouver les serveurs de backend et leur port.

Pour l’utilisation :

python bigIP_backendScan.py -u https://www.mytarget.tld

Quelques options sont disponibles et permettent :

  • De modifier le nombre de requête à effectuer, par défaut “50” :
python bigIP_backendScan.py -u http://mytarget.tld:8080 -r 100
  • De modifier le nom du cookie BigIP à rechercher. Par défaut, les cookies BigIP se nomment “BigIP-nom-duPool” mais on peut imaginer que les sysadmins aient modifié le nom du cookie pour enlever l’indication “BigIP” :
python bigIP_backendScan.py -u https://mytarget.tld:443 -n customBigIPCookieName

Voici une des sorties possibles :

[?] Trying to recover internal IP addresses from BIGIP cookies with following parameters:
 - target URL : [https://www.mytarget.tld] 
 - request number : [50]
 - cookie name [(BIGIP.*)].
[+] Collecting data...
    [+] 20%...
    [+] 40%...
    [+] 60%...
    [+] 80%...
[+] Processing data...
[+] Results :
[+] Cookie : BIGipServerp-http-www-mytarget-tld
    [+] 10.13.3.12:80
    [+] 10.13.3.14:80
[+] Cookie : BIGipServerp-http-another-target-tld
    [+] 10.13.3.18:80

On voit ici plusieurs éléments :

  • Les différentes IP utilisées pour constituer le pool
  • Le nom du pool assigné dans la configuration BigIP
  • Le port, et potentiellement le protocole utilisé entre le BigIP et les serveurs web en interne (80 = HTTP, non chiffré – 443 = https, chiffré)

À noter que dans la grande majorité des cas, le trafic entre le BigIP et les serveurs web est en HTTP (port 80).

Voici le github du script pour le télécharger et l’utiliser : https://github.com/nj8/bigIP_backendScan

Également, mon script Python peut permettre de gérer les cas où plusieurs cookies BigIP sont fournis dans une réponse pour un domaine, ce qui n’est pas le cas des autres outils que j’ai pu trouver.

Cette faille que l’on pourrait qualifier d’information leakage n’est pas une découverte récente, plusieurs articles de blog sont présents à ce sujet sur le net et une documentation de BigIP explique comment remédier à ce problème.

Outre le script, voici quelques informations supplémentaires autour de la manipulation du cookie BigIP :

  • Il est possible de choisir le serveur interne sur lequel on souhaite être redirigé. Il suffit pour cela, après avoir dressé une liste des serveurs disponibles et leur correspondance en IP:port au format décimal, de modifier notre cookie pour qu’il contienne la bonne chaîne. Une des exploitations possible est de bypasser le rôle du load-balancer pour viser toujours le même serveur. Ce qui, à l’échelle d’un botnet dédié au DDOS, peut être impactant : on focus un serveur, il tombe, on focus le suivant…
  • Il est impossible d’effectuer un scan interne visant d’autres ports ou IP que ceux présents dans la configuration du pool. Si l’on forge un cookie pour qu’il touche un autre port que le port 80 précisé dans la conf, un cookie nous est réassigné par BigIP.

A quoi ça sert ?

Il est maintenant temps de voir à quoi peuvent nous servir ces informations :

  • Intrusion – Social engineering

Dans un premier temps, connaître les informations du SI interne d’une entreprise peut servir dans une phase de social engineering. Prétendre être un sysadmin par exemple dans une grande entreprise qui en compte plusieurs dizaines, peut-être beaucoup plus facile lorsque l’on connaît des informations telles que les ranges IP internes, l’IP précise d’un pool configuré sur un load balancer. Cela permet de donner du crédit à l’attaquant qui construit son scénario de social engineering. Exemple :

Bonjour, je suis John, nouveau sysadmin dans l’entreprise XXX et j’ai un problème pour accéder au serveur membre du pool sousdomaine.domaine.tld sur notre F5 BigIP. Les serveurs membres du pool sont-ils bien les serveurs 10.5.0.56 et 10.5.0.58 ? Les identifiants que l’on m’a fourni sont correctes pour le second serveur mais je ne parviens pas à accéder au premier, est-il possible de me transmettre à nouveau ces informations ?”

La phase de social engineering se caractérise par une assurance et un charisme de l’attaquant, son but est de faire en sorte que la victime ne se pose pas une seule seconde la question de la légitimité de son interlocuteur, ce qui est beaucoup plus simple à mettre en place lorsque l’on connaît l’environnement dans lequel on évolue.

  • Cartographie – post exploitation

Dans une phase plus avancée de l’intrusion, celle de la post-exploitation, la connaissance des IP du pool BigIP nous permet de simplifier et d’accélérer l’évolution des pentesters. Lors d’une post-exploitation, il est important de rester le plus discret possible en évitant les scans d’IP ou de port notamment. Connaître ces informations depuis l’extérieur permet donc de gagner en efficacité lors de la post-exploitation.

Méthode de remédiation

Maintenant que nous avons compris comment ces informations pouvaient être obtenues et quels pouvaient en être les impacts, intéressons-nous aux méthodes de remédiation.

Il n’y a en réalité pas des centaines, comme je l’ai dit précédemment, cette fuite d’information est le comportement habituel dans la configuration par défaut de BigIP qui insère ces informations dans les cookies en possession des clients mais qui en plus ne chiffrent pas leur contenu.

La solution, prévue par la configuration BigIP, consiste donc à chiffrer le contenu des cookies. Le client sera donc toujours en possession de cette information mais il ne pourra pas la comprendre car elle sera chiffrée. Lorsque le répartiteur de charge BigIP recevra une requête contenant un cookie BigIP, il devra déchiffrer son contenu pour savoir où envoyer la requête du client.

Je vous oriente vers cette documentation pour plus d’informations sur la façon de procéder au niveau de la configuration :

N’hésitez pas à partager vos avis, améliorations et expériences autour du pentest Big IP dans les commentaires ! 🙂

Vous aimerez aussi...

1 réponse

  1. Jordan dit :

    Article très intéressant 🙂

Laisser un commentaire

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