
Analyse pas à pas de l'exploitation de CVE-2017-11610 (RCE XML-RPC de Supervisord) avec analyse de la surface d'attaque, découverte de traversée de namespace et techniques de post-exploitation dans un environnement de laboratoire Docker.
En commençant par ce qui tourne dans l'environnement. Je liste tous les conteneurs actifs :``` docker ps-a

**La victime expose un seul port : `9001`**.
Le port 9001 n'est pas une application web standard. La consultation de la **base de données des ports** montre que ce port pourrait être associé à **Supervisord** (ETL Service Manager selon l'IANA), au proxy Tor, ou à un autre service interne. Cependant, nous ne pouvons pas tirer de conclusion en nous basant uniquement sur le numéro de port.
⇒ Je fais un curl directement pour lire la réponse et j'accède également à l'interface graphique web afin de recueillir plus d'informations.```
curl -i http://192.168.3.137:9001/
Analyse de la réponse :
Server: Medusa/1.12 et le titre Supervisor Status→ Confirme qu'il s'agit de Supervisord, et non de Tor ou d'un autre service.
REFRESH, RESTART ALL, STOP ALLSupervisord est un gestionnaire de processus sous Linux. Si le port 9001 est exposé sur le réseau sans mot de passe, il s'agit d'une configuration dangereuse. Un attaquant pourrait consulter les services, redémarrer/arrêter des processus et, dans certaines configurations, l'exploiter pour exécuter des commandes s'il dispose des privilèges nécessaires pour modifier ou contrôler les programmes gérés.
Conclusion de l'analyse : Nous pouvons confirmer que la cible expose l'interface d'administration de Supervisord sur le réseau au port 9001. Il ne s'agit pas d'un service web standard, mais d'une interface de gestion utilisée pour surveiller et contrôler des processus. La possibilité d'accéder à cette interface sans authentification crée un risque qu'un attaquant puisse consulter l'état des services gérés ou interagir avec eux.
Cependant, il faut distinguer l'interface utilisateur visible du mécanisme de contrôle sous-jacent. Les boutons comme REFRESH, RESTART ALL et STOP ALL ne traitent pas les requêtes de manière indépendante côté frontend ; ils doivent faire appel à une interface/backend de Supervisord pour récupérer l'état ou envoyer des commandes de contrôle de processus. Par conséquent, après avoir confirmé que l'interface web est exposée, l'étape suivante de l'analyse consiste à déterminer si l'interface de contrôle sous-jacente existe derrière l'interface web et si elle nécessite une authentification.
⇒ Réflexion : Il faut vérifier si l'interface de contrôle derrière l'interface web existe et si elle nécessite une authentification.

Selon la documentation de Supervisor, [inet_http_server] est un serveur HTTP écoutant sur une socket TCP. Cette interface n'est pas activée par défaut, ne doit être utilisée que dans des environnements de confiance, ne prend pas en charge le chiffrement et ne dispose d'aucune authentification par défaut, sauf si username/password est configuré.
La documentation indique également que le port de [inet_http_server] sert à recevoir des requêtes HTTP/XML-RPC ; supervisorctl utilise XML-RPC pour communiquer avec supervisord via ce port. Cela correspond à notre observation en laboratoire : le conteneur expose 0.0.0.0:9001->9001/tcp, l'interface web est accessible sans authentification et la version affichée est Supervisor 3.3.2.
Ainsi, après avoir confirmé l'interface web sur le port 9001, l'étape suivante consiste à inspecter le point de terminaison XML-RPC /RPC2. Sur la base du mécanisme officiel de Supervisord, nous devons vérifier ces objectifs :
/RPC2 existe.supervisor.getState ou system.listMethods.Vérifions si le point de terminaison est actif :```
curl -i -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.getState'
http://192.168.3.137:9001/RPC2

Le résultat renvoie `HTTP/1.1 200 OK`, et non `401 Unauthorized` ou `403 Forbidden`, ce qui montre que la requête a été acceptée par le serveur sans informations d'identification. La réponse est au format XML-RPC `<methodResponse>` et contient `statename=RUNNING` et `statecode=1`, prouvant que le point de terminaison `/RPC2` est actif et que la méthode `supervisor.getState` a été exécutée avec succès.
**⇒ Réflexion :** La surface d'attaque n'est plus limitée à l'interface Web, mais s'est étendue à l'API XML-RPC, où sont gérées les commandes de contrôle du démon/des processus. À partir de là, la prochaine direction d'analyse consiste à **vérifier comment Supervisor** gère `methodName` dans **XML-RPC**, afin de déterminer si la cible actuelle **présente le comportement de CVE-2017-11610**, qui se situe dans le mécanisme de répartition/recherche de cette méthode. Nous devons vérifier cela pour conclure s'il s'agit de **CVE-2017-11610**.
### **Analyse du traitement du nom de méthode dans XML-RPC**
À l'étape précédente, nous avons appelé avec succès la méthode `supervisor.getState` via le point de terminaison `/RPC2`. Cela soulève la question suivante : lorsqu'il reçoit un `methodName` basé sur une chaîne, comment Supervisord mappe-t-il cette chaîne vers la fonction Python interne ?
En XML-RPC, les méthodes utilisent généralement des espaces de noms, par exemple :
- `supervisor.getState`
- `supervisor.stopProcess`
- `supervisor.getAllProcessInfo`
Logiquement, le serveur reçoit la chaîne `methodName`, la divise au niveau du point `.`, puis recherche l'objet/la fonction correspondante dans le gestionnaire enregistré.
Le pseudo-code peut être compris comme suit :```python
# Pseudo-code simulating the dispatch method concept in XML-RPC
def dispatch(method_name, params):
parts = method_name.split(".") # ["supervisor", "getState"]
obj = registered_handlers[parts[0]] # get namespace "supervisor"
for attr in parts[1:]:
obj = getattr(obj, attr) # lookup the next attribute
return obj(*params) # call the final function
For standard methods like supervisor.getState, this mechanism functions normally: the server retrieves the supervisor handler, then calls the getState function. However, the core issue of CVE-2017-11610 is that this lookup mechanism does not sufficiently restrict the attributes allowed to be accessed. If an attacker controls the methodName, they can not only call public methods like getState, but also traverse deeper into the internal objects/modules reachable from the supervisor handler.
In other words, the dot . in methodName is not just used to invoke valid methods, but can be abused to traverse object attributes.
This establishes our exploitation path:
supervisor → supervisord → options → warnings → linecache → os → system