Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-66418-OpenClaw-Dashboard-v3.0.0-Stored-XSS-via-Failed-Login-Username-Field — Avviso di Sicurezza: Cross-Site Scripting Memorizzato Non Autenticato che Porta all'Acquisizione dell'Account Amministratore (openclaw-dashboard) | Kitploit
Strumenti/GitHubGitHub/theopaid/cve-2026-66418-openclaw-dashboard-v3.0.0-stored-xss-via-failed-login-username-field
Analisi delle VulnerabilitàSfruttamento di Applicazioni WebSicurezza WebApprendimento e Formazione
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

Avviso di Sicurezza: Cross-Site Scripting Memorizzato Non Autenticato che Porta all'Acquisizione dell'Account Amministratore (openclaw-dashboard)

Vedi Repository

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
18 giorni faNon ancora revisionato

Advisory di sicurezza: Cross-Site Scripting persistente non autenticato che porta al takeover dell'account amministratore (openclaw-dashboard)

Titolo: OpenClaw Dashboard v3.0.0 Stored XSS tramite il campo Username del login fallito ID CVE assegnato: CVE-2026-66418

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

Riepilogo

L'endpoint di login registra lo username inviato nel log di audit senza alcuna validazione. Il pannello delle notifiche legge successivamente quelle voci di log e le scrive nella pagina con innerHTML e senza escape. Un attaccante che non può accedere può comunque inviare una richiesta di login fallita il cui username è un payload di script. La volta successiva in cui l'amministratore autenticato apre la campanella delle notifiche, il payload viene eseguito nel suo browser, nell'origine della dashboard, con accesso al suo token di sessione.

  • CWE-79: Neutralizzazione impropria dell'input durante la generazione della pagina web (Cross-site Scripting)
  • CWE-117: Neutralizzazione impropria dell'output per i log
  • CVSS 4.0: 9.3 (Critico). Vector: 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

Versioni interessate

Introdotta nella v3.0.0, che ha aggiunto il centro notifiche che visualizza le voci del log di audit. Presente nella v3.0.0 e in ogni commit successivo fino a includere l'attuale main (d6198d0). Non risolta al momento della stesura.

Modello di minaccia

L'attaccante è un soggetto remoto che può raggiungere la porta HTTP della dashboard ma non possiede un account né credenziali valide. Ciò corrisponde alla schermata di login raggiungibile da chiunque possa aprire la dashboard. L'unica precondizione è che esista già un account amministratore, il che è vero per qualsiasi distribuzione oltre la configurazione iniziale.

Il payload è persistente, quindi non è necessaria alcuna coordinazione temporale. Viene eseguito quando l'amministratore apre il pannello delle notifiche, un'azione normale offerta dall'interfaccia. Una volta eseguito, ha le stesse capacità del browser dell'amministratore: può leggere il token di sessione e chiamare qualsiasi endpoint autenticato per conto della vittima.

Causa principale

Passaggio 1. Lo username viene registrato nei log così com'è. Un login con uno username che non corrisponde all'account registrato raggiunge questo ramo:

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 arriva direttamente dal corpo della richiesta JSON. Non esiste alcun limite di lunghezza, allowlist di caratteri o controllo del tipo. auditLog lo scrive su disco come riga JSON:

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 esegue l'escape di virgolette e newline, quindi il payload rimane su una sola riga e viene rieseguito in parsing correttamente. Non esegue l'escape di <, > o /, quindi il markup HTML sopravvive intatto.

Passaggio 2. Il log viene riletto. L'endpoint delle notifiche restituisce le righe di log recenti al browser:

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 }));

Passaggio 3. Lo username viene scritto nel DOM senza escape. Il frontend costruisce ogni riga di notifica tramite concatenazione di stringhe e la assegna con innerHTML:

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 è la stringa dell'attaccante. Raggiunge innerHTML senza alcuna codifica, quindi il browser la interpreta come HTML.

La Content-Security-Policy impostata in server.js:298 include script-src 'self' 'unsafe-inline', quindi i gestori di eventi inline come onerror possono essere eseguiti.

Prova di concetto

  1. Assicurarsi che esista un account amministratore (qualsiasi installazione normale). L'attaccante non ha bisogno delle sue credenziali.

  2. In qualità di attaccante non autenticato, inviare un login fallito il cui username è il payload:

    root@kitploit:~
    curl -X POST http://TARGET:7000/api/auth/login \
      -H 'Content-Type: application/json' \
      -d '{"username":"","password":"x"}'
    
  3. L'amministratore accede normalmente e fa clic sulla campanella delle notifiche.

  4. Il payload viene eseguito nella sessione dell'amministratore. In questo esempio legge il token di sessione con il getStoredToken() della pagina e lo usa per sovrascrivere il file di istruzioni dell'agente AGENTS.md tramite POST /api/key-file. Qualsiasi endpoint autenticato può essere chiamato allo stesso modo.

Il testo del payload rimane su una singola riga di log e torna byte per byte tramite /api/notifications, quindi l'iniezione e l'esecuzione possono essere confermate separatamente.

Impatto

Esecuzione di codice nell'origine della dashboard con i privilegi dell'amministratore. Lo script può leggere il token di sessione e inviare qualsiasi richiesta autenticata, inclusa la modifica dei file di istruzioni e delle skill dell'agente e la modifica della configurazione di OpenClaw. Poiché l'attaccante non ha bisogno di un account, una richiesta di rete non autenticata si trasforma nel controllo della sessione dell'amministratore.

Rimedio

  • Codificare in HTML ogni valore prima di inserirlo in innerHTML, oppure costruire i nodi con textContent invece della concatenazione di stringhe. I campi username, evento e IP delle notifiche richiedono tutti questo trattamento.
  • Validare username sul server prima di registrarlo nei log: limitarne la lunghezza e restringerlo a un set di caratteri previsto.
  • Rimuovere 'unsafe-inline' da script-src. Con i gestori inline bloccati, questo problema scende da esecuzione di codice a markup innocuo.
Scarica lo strumento