Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-66418-OpenClaw-Dashboard-v3.0.0-Stored-XSS-via-Failed-Login-Username-Field — Aviso de Segurança: Cross-Site Scripting Armazenado Não Autenticado Levando à Tomada de Conta de Administrador (openclaw-dashboard) | Kitploit
Ferramentas/GitHubGitHub/theopaid/cve-2026-66418-openclaw-dashboard-v3.0.0-stored-xss-via-failed-login-username-field
Análise de VulnerabilidadesExploração de Aplicações WebSegurança WebAprendizado e Educação
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

Aviso de Segurança: Cross-Site Scripting Armazenado Não Autenticado Levando à Tomada de Conta de Administrador (openclaw-dashboard)

Ver Repositório

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
há 17 diasAinda não revisado

Aviso de Segurança: Cross-Site Scripting Armazenado Não Autenticado Levando à Assunção da Conta de Administrador (openclaw-dashboard)

Título: OpenClaw Dashboard v3.0.0 XSS Armazenado via Campo de Nome de Usuário de Login Falho ID de CVE atribuído: CVE-2026-66418

Repositório alvo: https://github.com/tugcantopaloglu/openclaw-dashboard

Resumo

O endpoint de login registra o nome de usuário submetido no log de auditoria sem qualquer validação. O painel de notificações depois lê essas entradas de log e as escreve na página com innerHTML e sem escape. Um atacante que não consegue fazer login ainda pode enviar uma solicitação de login falha cujo nome de usuário seja um payload de script. Na próxima vez que o administrador logado abrir o sino de notificações, esse payload será executado no navegador dele, na origem do dashboard, com acesso ao token de sessão.

  • CWE-79: Neutralização Incorreta de Entrada Durante a Geração de Página da Web (Cross-site Scripting)
  • CWE-117: Neutralização Incorreta de Saída para Logs
  • CVSS 4.0: 9.3 (Crítico). Vetor: 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

Versões afetadas

Introduzido na v3.0.0, que adicionou a central de notificações que renderiza as entradas do log de auditoria. Presente na v3.0.0 e em todos os commits posteriores até e incluindo o main atual (d6198d0). Não corrigido no momento em que este texto foi escrito.

Modelo de ameaça

O atacante é uma parte remota que consegue alcançar a porta HTTP do dashboard, mas não tem conta nem credenciais válidas. Isso corresponde à tela de login ser acessível por qualquer pessoa que possa abrir o dashboard. A única pré-condição é que uma conta de administrador já exista, o que é verdade para qualquer implantação após a configuração inicial.

O payload é armazenado, portanto não é necessária coordenação de tempo. Ele é executado quando o administrador abre o painel de notificações, que é uma ação normal oferecida pela interface. Uma vez executado, ele tem as mesmas capacidades que o navegador do administrador: pode ler o token de sessão e chamar qualquer endpoint autenticado em nome da vítima.

Causa raiz

Passo 1. O nome de usuário é registrado literalmente. Um login com um nome de usuário que não corresponde à conta registrada chega a este trecho:

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 vem diretamente do corpo da solicitação JSON. Não há limite de comprimento, lista de caracteres permitidos ou verificação de tipo. auditLog o escreve em disco como uma linha 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 escapa aspas e quebras de linha, então o payload permanece em uma única linha e é analisado de volta corretamente. Ele não escapa <, > ou /, portanto a marcação HTML sobrevive intacta.

Passo 2. O log é lido de volta. O endpoint de notificações retorna linhas de log recentes ao navegador:

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

Passo 3. O nome de usuário é escrito no DOM sem escape. O front-end constrói cada linha de notificação por concatenação de strings e a atribui com 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 é a string do atacante. Ela chega ao innerHTML sem codificação, então o navegador a interpreta como HTML.

A Content-Security-Policy definida em server.js:298 inclui script-src 'self' 'unsafe-inline', portanto manipuladores de eventos inline como onerror podem ser executados.

Prova de conceito

  1. Certifique-se de que existe uma conta de administrador (qualquer instalação normal). O atacante não precisa das credenciais dela.

  2. Como atacante não autenticado, envie um login falho cujo nome de usuário seja o payload:

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

    O servidor responde 401 Invalid username or password e armazena o payload.

  3. O administrador faz login normalmente e clica no sino de notificações.

  4. O payload é executado na sessão do administrador. Neste exemplo, ele lê o token de sessão com o getStoredToken() da própria página e o usa para sobrescrever o arquivo de instruções do agente AGENTS.md através de POST /api/key-file. Qualquer endpoint autenticado pode ser chamado da mesma forma.

O texto do payload permanece como uma única linha de log e retorna byte por byte através de /api/notifications, portanto a injeção e a execução podem ser confirmadas separadamente.

Impacto

Execução de código na origem do dashboard como o administrador. O script pode ler o token de sessão e emitir qualquer solicitação autenticada, incluindo editar os arquivos de instrução e habilidades do agente e alterar a configuração do OpenClaw. Como o atacante não precisa de conta, isso transforma uma solicitação de rede não autenticada no controle da sessão do administrador.

Remediação

  • Codifique em HTML todo valor antes de colocá-lo em innerHTML, ou construa nós com textContent em vez de concatenação de strings. Os campos de nome de usuário, evento e IP da notificação precisam disso.
  • Valide username no servidor antes de registrá-lo: limite seu comprimento e restrinja-o a um conjunto de caracteres esperado.
  • Remova 'unsafe-inline' de script-src. Com os manipuladores inline bloqueados, este problema cai de execução de código para marcação inofensiva.
Baixar ferramenta