
CVE-2026-39275 - XSS armazenado levando à tomada de conta no Cockpit CMS
Nota: Divulgado de forma responsável e corrigido pelos mantenedores do Cockpit CMS antes da publicação.
| ID do CVE | CVE-2026-39275 |
| Vulnerabilidade | Cross-Site Scripting Armazenado (XSS) → Tomada de Conta |
| CWE | CWE-79 |
| Afetado | Cockpit CMS <= 2.13.5 |
| Corrigido | d70dc50 |
| CVSS 3.1 | 8.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N) |
| Relator | Rohith - Consultor de Segurança @ SecurifyAI |
Uma vulnerabilidade de XSS armazenado na visualização da lista de coleções de conteúdo permite que qualquer usuário com acesso de escrita ao conteúdo (uma chave de API ou uma sessão de editor autenticado) injete JavaScript arbitrário que é executado no navegador de qualquer administrador ou editor que visualize a lista de itens da coleção afetada.
Os tokens de sessão do Cockpit são totalmente acessíveis a partir do JavaScript - o cookie de sessão é definido sem a flag HttpOnly, e o JWT CSRF é exposto na variável global App.csrf e no atributo data-csrf no <html>. Isso permite que o script injetado leia ambos os tokens e os reproduza externamente, contornando a proteção CSRF e permitindo o sequestro completo da sessão e a tomada de conta.
As saídas do campo render() são passadas para a diretiva v-html do Vue sem codificação de saída.
| Arquivo | Linha(s) | Função |
|---|---|---|
modules/App/assets/vue-components/fields/field-tags.js | 25 - 34 | Renderizador de tags - sem codificação |
modules/App/assets/vue-components/fields/field-select.js | 26 | Renderizador de seleção - sem codificação |
modules/Content/views/collection/items.php | 149 | Coletor v-html |
curl -X POST "http://localhost:8080/api/content/item/posts" \
-H "Content-Type: application/json" \
-H "api-key: USR-<attacker-api-key>" \
-d '{
"data": {
"title": "Innocent Looking Post",
"tags": [
"",
""
],
"body": "Just a regular post.",
"_state": 1
}
}'
Um administrador ou editor navega para /content/collection/items/posts. O renderizador de tags retorna a string armazenada, v-html a analisa em um elemento `` real, o src falso falha e o manipulador onerror é acionado.
Ambos os tokens agora são legíveis - o cookie de sessão via document.cookie e o JWT CSRF via App.csrf / document.documentElement.getAttribute('data-csrf'). Um payload armado exfiltra ambos:
O atacante reproduz o cookie e o token CSRF roubados, obtendo acesso de administrador totalmente autenticado - e pode então criar contas de administrador, alterar credenciais ou modificar conteúdo.
Um editor com privilégios baixos (ou qualquer detentor de chave de API de escrita de conteúdo) escala para administrador completo. O payload é armazenado e é acionado para cada administrador/editor que visualiza a lista, tornando-o um comprometimento persistente e com múltiplas vítimas.
Correção principal - sanitizar a saída do renderizador antes que ela alcance v-html usando o helper existente App.utils.stripTags().
field-tags.js:
value = App.utils.stripTags(value); // sanitize before v-html
field-select.js:
return App.utils.stripTags(value); // sanitize before v-html
Defesa em profundidade - endurecer o cookie de sessão:
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1); // over HTTPS
ini_set('session.cookie_samesite', 'Strict');
HttpOnly sozinho é insuficiente - o XSS ainda pode agir dentro do contexto autenticado do navegador da vítima - portanto, a codificação de saída é a correção essencial.
| Data | Evento |
|---|---|
| 2026-03-29 | Vulnerabilidade reportada aos mantenedores do Cockpit CMS |
| 2026-03-29 | Correção lançada pelos mantenedores |
| 2026-04-04 | CVE solicitado |
| 2026-06-23 | CVE-2026-39275 atribuído |
<pub date> | Divulgação pública |
Este material é publicado para fins educacionais e defensivos após divulgação coordenada. Use apenas contra sistemas que você possui ou está explicitamente autorizado a testar.