
Preuves de concept d'exploitation pour les vulnérabilités du cluster Wazuh CVE-2026-25769 et CVE-2026-25770, démontrant l'exécution de code à distance et l'élévation de privilèges via une désérialisation non sécurisée et l'écrasement de fichiers.
Avertissement : Ce dépôt contient des informations et du code liés à des vulnérabilités de sécurité. Utilisez-le uniquement à des fins éducatives ou dans des environnements autorisés.
Deux vulnérabilités critiques ont été identifiées dans la configuration du cluster Wazuh (versions ≥ 4.0.0). Ces failles affectent les déploiements qui utilisent plusieurs nœuds pour l'évolutivité horizontale, l'équilibrage de charge et la haute disponibilité. Cette configuration permet la gestion de plusieurs agents sans impact sur le serveur Wazuh.
Permet la communication entre le master et le worker via une requête DAPi. Le worker envoie un objet en utilisant le module LocalClient du worker ; le master accepte le message et désérialise l'objet avec la fonction vulnérable as_wazuh_object(), ce qui permet d'exécuter des commandes sur le master.
Cette vulnérabilité complète la précédente, permettant l'exécution de commandes via les balises <command> et <localfile>. Un attaquant peut exécuter des commandes à chaque chargement du fichier de configuration /var/ossec/etc/ossec.conf.
Les deux permettent [impact général : élévation de privilèges, exécution à distance, etc.] dans les environnements qui utilisent la fonctionnalité de cluster.
Wazuh manager ≥ 4.0.0 (jusqu'à la version corrigée X.Y.Z)
Tous les nœuds avec le rôle master ou worker ayant la communication entre nœuds activée.
La configuration du cluster est utilisée dans les déploiements avec un grand nombre d'agents. Elle permet :
Évolutivité horizontale : ajouter plus de nœuds workers pour répartir la charge.
Haute disponibilité : si un nœud worker tombe en panne, les autres continuent de fonctionner pendant que le nœud est restauré.
Équilibrage de charge : les agents sont répartis entre les workers.
Cette architecture, si elle n'est pas correctement sécurisée, peut exposer des vecteurs d'attaque comme ceux documentés ici.
Le master appelle cette fonction, qui permet la création d'un sous-processus exécutant arbitrairement des commandes.
def as_wazuh_object(dct: Dict):
try:
if '__callable__' in dct:
encoded_callable = dct['__callable__']
funcname = encoded_callable['__name__'] #getoutput
if '__wazuh__' in encoded_callable:
# Encoded Wazuh instance method.
wazuh = Wazuh()
return getattr(wazuh, funcname)
else:
# Encoded function or static method.
qualname = encoded_callable['__qualname__'].split('.') # getoutput
classname = qualname[0] if len(qualname) > 1 else None
module_path = encoded_callable['__module__'] # subprocess
module = import_module(module_path) # ARBITRARY IMPORT
if classname is None:
return getattr(module, funcname) # RETURNS ARBITRARY FUNCTION
else:
return getattr(getattr(module, classname), funcname)
Le protocole de cluster Wazuh (TCP/1516) synchronise les fichiers entre les nœuds en utilisant le processus. Ce processus s'exécute en tant qu'utilisateur non privilégié, acceptant des chemins relatifs.
"""Create a file descriptor to store the incoming file.
Parameters
----------
data : bytes
Relative path to the file.
Returns
-------
bytes
Result.
bytes
Response message.
"""
# VULNERABLE LINE: No validation of 'data', no checking for '../', direct file open.
self.in_file[data] = {'fd': open(common.WAZUH_PATH + data.decode(), 'wb'), 'checksum': hashlib.sha256()}
return b"ok ", b"Ready to receive new file"
En utilisant cette configuration, un attaquant pourrait écraser le répertoire de configuration et parvenir à exécuter des commandes.
Un attaquant pourrait :
Affecter la confidentialité, l'intégrité, la disponibilité et l'élévation de privilèges.
Compromettre l'intégrité de toute l'infrastructure surveillée.
Les PoC originaux ont été développés par vikman90 et ont servi de base à cette analyse. Un exemple d'exploitation est présenté ci-dessous :
# 1. init docker compose
docker compose up -d
# 2. wait init all clusters
# 3. Verify cluster is connected
docker exec poc-master /var/ossec/bin/cluster_control -l
# Expected output should show worker01 connected:
# worker01 172.28.0.11 active
# 4. Execute exploit from worker
docker exec poc-worker /var/ossec/framework/python/bin/python3 /scripts/poc.py
# 5. Verify RCE on master
docker exec poc-master cat /var/ossec/etc/ossec.conf