Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-66421-OpenClaw-Dashboard-Stored-XSS-via-lastMessage-Session-Field — Avis de sécurité : Cross-Site Scripting stocké via les messages d'agent conduisant au vol de jeton de session (openclaw-dashboard) | Kitploit
Outils/GitHubGitHub/theopaid/cve-2026-66421-openclaw-dashboard-stored-xss-via-lastmessage-session-field
Analyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebSécurité des APISécurité de l'IA
GitHubtheopaid/cve-2026-66421-openclaw-dashboard-stored-xss-via-lastmessage-session-field

CVE-2026-66421-OpenClaw-Dashboard-Stored-XSS-via-lastMessage-Session-Field

Avis de sécurité : Cross-Site Scripting stocké via les messages d'agent conduisant au vol de jeton de session (openclaw-dashboard)

Voir le dépôt
5il y a 1 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Avis de sécurité : Cross-Site Scripting stocké via les messages de l'agent conduisant au vol de jeton de session (openclaw-dashboard)

Titre : XSS stocké sur OpenClaw Dashboard via le champ de session lastMessage ID CVE : CVE-2026-66421

https://github.com/tugcantopaloglu/openclaw-dashboard

Résumé

La table des sessions de la page d'accueil du tableau de bord affiche le dernier message de chaque session d'agent. Ce texte est extrait de la transcription de la conversation de l'agent puis écrit dans la page avec innerHTML, sans échappement. OpenClaw étant une passerelle multi-canaux pour agents, le texte du message peut provenir de toute personne capable de parler à l'agent, comme un groupe de discussion ou un webhook. Un message contenant une charge utile HTML s'exécute comme script dans le navigateur de l'administrateur dès qu'il ouvre le tableau de bord.

  • CWE-79 : Neutralisation incorrecte des entrées lors de la génération de pages Web (Cross-site Scripting)
  • CVSS 4.0 : 8.8 (Élevé). Vecteur : CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N

Versions concernées

Présente depuis la première publication publique. Le rendu vulnérable existe dans le tout premier tag (v1.1.0) et dans chaque commit ultérieur jusqu'au main actuel inclus (d6198d0). Non corrigé au moment de la rédaction.

Modèle de menace

L'attaquant est une partie capable d'envoyer un message qui atterrit dans la transcription de session de l'agent. Il n'a pas besoin de compte sur le tableau de bord. Dans un déploiement OpenClaw typique, cela inclut les membres des canaux de discussion connectés et toute source qui atteint l'agent via un webhook. L'attaquant se trouve donc souvent en dehors de la frontière de confiance de l'opérateur.

La charge utile est stockée dans la transcription et rendue à chaque fois que l'administrateur consulte la page des sessions. Cette page est la vue d'accueil par défaut et se rafraîchit sur une minuterie, donc la seule interaction requise est que l'administrateur charge le tableau de bord qu'il utilise normalement. AT:P reflète l'unique condition sur laquelle s'appuie l'attaquant : que le déploiement route ses messages vers une session affichée par le tableau de bord.

Cause racine

Étape 1. Le texte du message est extrait de la transcription. Le serveur lit le message le plus récent et renvoie son texte, tronqué à 80 caractères, sans assainissement :

root@kitploit:~
// server.js:474-481
if (typeof msg.content === 'string') {
  text = msg.content;
} else if (Array.isArray(msg.content)) {
  for (const b of msg.content) {
    if (b.type === 'text' && b.text) { text = b.text; break; }
  }
}
if (text) return text.replace(/\n/g, ' ').substring(0, 80);

Étape 2. Il est exposé via l'API des sessions. getSessionsJson place le texte dans le champ lastMessage de chaque session :

root@kitploit:~
// server.js:538
lastMessage: getLastMessage(s.sessionId || key),

GET /api/sessions renvoie ce tableau au navigateur.

Étape 3. Il est écrit dans le DOM sans échappement. La table des sessions construit chaque ligne par concaténation de chaînes et l'affecte via innerHTML :

root@kitploit:~
// index.html:3758
const lastMsg = s.lastMessage ? s.lastMessage.substring(0, 60) + (s.lastMessage.length > 60 ? '…' : '') : '';
root@kitploit:~
// index.html:3773
<div class="table-cell" style="..." onclick="toggleSessionExpand('${escapedKey}', event)">${lastMsg}</div>

lastMsg est placé directement dans la chaîne HTML. Aucune étape d'encodage n'existe sur ce chemin.

La même table interpole s.label (index.html:3770) et s.key (index.html:3767) dans le balisage de la ligne de la même manière. Ces champs n'ont pas de limite de 60 caractères, ce qui laisse à un attaquant capable de les influencer plus d'espace pour une charge utile.

La Content-Security-Policy à server.js:298 autorise les gestionnaires d'événements en ligne (script-src 'self' 'unsafe-inline'), donc un gestionnaire onerror s'exécute.

Preuve de concept

  1. En tant que partie pouvant envoyer un message à l'agent, envoyez un message dont le texte est une charge utile courte qui tient dans le budget de 60 caractères, par exemple :

    root@kitploit:~

    Cela fait 56 caractères et atteint la transcription de session de l'agent comme n'importe quel message normal.

  2. Confirmez que le serveur renvoie la charge utile sans échappement :

    root@kitploit:~
    curl -H "Authorization: Bearer ADMIN_TOKEN" http://TARGET:7000/api/sessions
    

    Le champ lastMessage de la session concernée contient la chaîne brute ``.

  3. L'administrateur ouvre le tableau de bord. La page des sessions est la vue par défaut, donc aucune navigation supplémentaire n'est nécessaire. La ligne est rendue, le navigateur analyse la balise ``, le gestionnaire onerror s'exécute et le jeton de session de l'administrateur est lu par la charge utile.

Remplacer le corps du console.log par un fetch vers un point de terminaison authentifié de même origine permet à la charge utile d'agir avec les privilèges de l'utilisateur connecté.

Impact

Exécution de script dans l'origine du tableau de bord en tant qu'utilisateur connecté, accessible à toute personne qui n'a qu'à envoyer un message à l'agent. La charge utile peut lire le jeton de session et appeler des points de terminaison authentifiés, y compris ceux qui modifient les fichiers d'instructions de l'agent lui-même et la configuration OpenClaw. Comme elle se déclenche sur la page par défaut, l'administrateur n'a aucune action inhabituelle à effectuer.

Remédiation

  • Encoder en HTML lastMessage, label et key avant de les insérer dans le balisage de la ligne, ou construire les cellules avec textContent plutôt qu'avec une chaîne HTML.
  • Appliquer le même encodage aux autres champs de session rendus via innerHTML.
  • Retirer 'unsafe-inline' de script-src afin que le balisage injecté ne puisse pas s'exécuter même si une étape d'encodage est manquée.
Télécharger l’outil