Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-66418-OpenClaw-Dashboard-v3.0.0-Stored-XSS-via-Failed-Login-Username-Field — Sicherheitshinweis: Nicht authentifiziertes, gespeichertes Cross-Site Scripting führt zur Übernahme von Administrator-Konten (openclaw-dashboard) | Kitploit
Tools/GitHubGitHub/theopaid/cve-2026-66418-openclaw-dashboard-v3.0.0-stored-xss-via-failed-login-username-field
SchwachstellenanalyseWebanwendungs-ExploitationWebsicherheitLernen & Bildung
GitHubtheopaid/cve-2026-66418-openclaw-dashboard-v3.0.0-stored-xss-via-failed-login-username-field

CVE-2026-66418-OpenClaw-Dashboard-v3.0.0-Stored-XSS-via-Failed-Login-Username-Field

Sicherheitshinweis: Nicht authentifiziertes, gespeichertes Cross-Site Scripting führt zur Übernahme von Administrator-Konten (openclaw-dashboard)

Repository anzeigen

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
vor 18 TagenNoch nicht geprüft

Sicherheitshinweis: Nicht authentifiziertes gespeichertes Cross-Site-Scripting führt zur Übernahme eines Administrator-Kontos (openclaw-dashboard)

Titel: OpenClaw Dashboard v3.0.0 – Gespeichertes XSS über das Benutzernamenfeld bei fehlgeschlagenem Login Zugewiesene CVE-ID: CVE-2026-66418

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

Zusammenfassung

Der Login-Endpunkt zeichnet den übermittelten Benutzernamen ohne jegliche Validierung im Audit-Log auf. Das Benachrichtigungsfeld liest diese Logeinträge später aus und schreibt sie mit innerHTML und ohne Escaping in die Seite. Ein Angreifer, der sich nicht anmelden kann, kann dennoch eine fehlgeschlagene Login-Anfrage senden, deren Benutzername ein Skript-Payload ist. Beim nächsten Öffnen der Benachrichtigungsglocke durch den angemeldeten Administrator wird dieser Payload im Browser des Administrators ausgeführt – im Ursprung des Dashboards und mit Zugriff auf dessen Sitzungstoken.

  • CWE-79: Unangemessene Neutralisierung von Eingaben während der Webseitengenerierung (Cross-Site-Scripting)
  • CWE-117: Unangemessene Neutralisierung der Ausgabe für Logs
  • CVSS 4.0: 9.3 (Kritisch). Vektor: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N

Betroffene Versionen

Eingeführt in v3.0.0, das das Benachrichtigungszentrum hinzufügte, das Audit-Log-Einträge rendert. Vorhanden in v3.0.0 und in jedem späteren Commit bis einschließlich des aktuellen main (d6198d0). Zum Zeitpunkt des Schreibens nicht behoben.

Bedrohungsmodell

Der Angreifer ist eine entfernte Partei, die den HTTP-Port des Dashboards erreichen kann, aber weder ein Konto noch gültige Anmeldedaten besitzt. Dies entspricht der Tatsache, dass der Login-Bildschirm für jeden erreichbar ist, der das Dashboard öffnen kann. Die einzige Voraussetzung ist, dass bereits ein Administrator-Konto existiert, was für jede Bereitstellung nach der Ersteinrichtung gilt.

Der Payload wird gespeichert, daher ist keine zeitliche Koordination erforderlich. Er wird ausgeführt, wenn der Administrator das Benachrichtigungsfeld öffnet, eine normale, von der UI angebotene Aktion. Sobald er läuft, besitzt er dieselben Fähigkeiten wie der Browser des Administrators: Er kann das Sitzungstoken lesen und jeden authentifizierten Endpunkt im Namen des Opfers aufrufen.

Grundursache

Schritt 1: Der Benutzername wird wörtlich protokolliert. Ein Login mit einem Benutzernamen, der nicht mit dem registrierten Konto übereinstimmt, erreicht diesen Zweig:

root@kitploit:~
// server.js:1577-1583
if (username !== creds.username) {
  recordFailedAuth(ip);
  auditLog('login_failed', ip, { username });
  res.writeHead(401, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ error: 'Invalid username or password' }));
  return;
}

username stammt direkt aus dem JSON-Anfragetext. Es gibt keine Längenbegrenzung, keine Zeichen-Allowlist und keine Typüberprüfung. auditLog schreibt den Eintrag als JSON-Zeile auf die Festplatte:

root@kitploit:~
// server.js:278-282
function auditLog(event, ip, details = {}) {
  try {
    const timestamp = new Date().toISOString();
    const entry = JSON.stringify({ timestamp, event, ip, ...details }) + '\n';
    fs.appendFileSync(auditLogPath, entry, 'utf8');

JSON.stringify maskiert Anführungszeichen und Zeilenumbrüche, sodass der Payload in einer Zeile bleibt und sich sauber zurückparsen lässt. Es maskiert jedoch weder <, > noch /, sodass HTML-Markup unversehrt erhalten bleibt.

Schritt 2: Das Log wird zurückgelesen. Der Notifications-Endpunkt gibt die letzten Logzeilen an den Browser zurück:

root@kitploit:~
// server.js:2042-2051
if (req.url.startsWith('/api/notifications')) {
  if (!requireAuth(req, res)) return;
  const limit = parseInt(new URL(req.url, 'http://localhost').searchParams.get('limit') || '50');
  try {
    const raw = fs.readFileSync(auditLogPath, 'utf8').trim();
    const lines = raw.split('\n').filter(Boolean).slice(-Math.min(limit, 200));
    const events = lines.map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean).reverse();
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ events }));

Schritt 3: Der Benutzername wird ohne Escaping in das DOM geschrieben. Das Frontend erstellt jede Benachrichtigungszeile per String-Konkatenation und weist sie über innerHTML zu:

root@kitploit:~
// index.html:5647-5653
body.innerHTML = data.events.map(e => {
  const icon = notifIcons[e.event] || '📋';
  const time = e.timestamp ? new Date(e.timestamp).toLocaleString() : '';
  const detail = e.username ? ' (' + e.username + ')' : '';
  const ip = e.ip ? ' from ' + e.ip : '';
  return '<div class="notif-item"><div class="notif-icon">' + icon + '</div><div class="notif-content"><div class="notif-event">' + (e.event||'').replace(/_/g, ' ') + detail + ip + '</div><div class="notif-time">' + time + '</div></div></div>';
}).join('');

e.username ist die Zeichenkette des Angreifers. Sie gelangt ohne Kodierung zu innerHTML, sodass der Browser sie als HTML parst.

Die in server.js:298 festgelegte Content-Security-Policy enthält script-src 'self' 'unsafe-inline', sodass Inline-Ereignishandler wie onerror ausgeführt werden dürfen.

Proof of Concept

  1. Stellen Sie sicher, dass ein Administrator-Konto vorhanden ist (bei jeder normalen Installation). Der Angreifer benötigt dessen Anmeldedaten nicht.

  2. Senden Sie als nicht authentifizierter Angreifer einen fehlgeschlagenen Login, dessen Benutzername der Payload ist:

    root@kitploit:~
    curl -X POST http://TARGET:7000/api/auth/login \
      -H 'Content-Type: application/json' \
      -d '{"username":"","password":"x"}'
    

    Der Server antwortet mit 401 Invalid username or password und speichert den Payload.

  3. Der Administrator meldet sich normal an und klickt auf die Benachrichtigungsglocke.

  4. Der Payload läuft in der Sitzung des Administrators. In diesem Beispiel liest er das Sitzungstoken mit der eigenen getStoredToken()-Methode der Seite und verwendet es, um die Agenten-Anweisungsdatei AGENTS.md über POST /api/key-file zu überschreiben. Jeder authentifizierte Endpunkt kann auf dieselbe Weise aufgerufen werden.

Der Payload-Text bleibt eine einzelne Logzeile und kommt über /api/notifications Byte für Byte zurück, sodass Injektion und Ausführung getrennt bestätigt werden können.

Auswirkungen

Codeausführung im Ursprung des Dashboards mit den Rechten des Administrators. Das Skript kann das Sitzungstoken lesen und beliebige authentifizierte Anfragen stellen, einschließlich der Bearbeitung der Anweisungs- und Fähigkeitsdateien des Agents und der Änderung der OpenClaw-Konfiguration. Da der Angreifer kein Konto benötigt, wird aus einer nicht authentifizierten Netzwerkanfrage die Kontrolle über die Sitzung des Administrators.

Behebung

  • Kodieren Sie jeden Wert als HTML, bevor Sie ihn in innerHTML einfügen, oder erstellen Sie Knoten mit textContent anstelle von String-Konkatenation. Die Benachrichtigungsfelder für Benutzername, Ereignis und IP benötigen dies alle.
  • Validieren Sie username auf dem Server, bevor Sie ihn protokollieren: Begrenzen Sie seine Länge und beschränken Sie ihn auf einen erwarteten Zeichensatz.
  • Entfernen Sie 'unsafe-inline' aus script-src. Wenn Inline-Handler blockiert sind, reduziert sich dieses Problem von Codeausführung auf harmloses Markup.
Tool herunterladen