
CVE-2026-39275 - XSS memorizzato che porta al furto dell'account in Cockpit CMS
| ID CVE | CVE-2026-39275 |
| Vulnerabilità | Stored Cross-Site Scripting (XSS) → Furto dell'Account |
| CWE | CWE-79 |
| Versioni affette | Cockpit CMS <= 2.13.5 |
| Corretta in | d70dc50 |
| CVSS 3.1 | 8.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N) |
| Segnalato da | Rohith - Security Consultant @ SecurifyAI |
Una vulnerabilità XSS memorizzata nella visualizzazione dell'elenco delle raccolte di contenuti consente a qualsiasi utente con permessi di scrittura (una chiave API o una sessione editor autenticata) di iniettare JavaScript arbitrario che viene eseguito nel browser di qualsiasi amministratore o editor che visualizza l'elenco degli elementi della raccolta interessata.
I token di sessione di Cockpit sono completamente accessibili da JavaScript - il cookie di sessione è impostato senza il flag HttpOnly, e il JWT CSRF è esposto nella variabile globale App.csrf e nell'attributo data-csrf su <html>. Ciò consente allo script iniettato di leggere entrambi i token e riprodurli esternamente, aggirando la protezione CSRF e consentendo il dirottamento completo della sessione e il furto dell'account.
Gli output di render() dei campi vengono passati alla direttiva v-html di Vue senza codifica dell'output.
| File | Riga/e | Ruolo |
|---|---|---|
modules/App/assets/vue-components/fields/field-tags.js | 25 - 34 | Render tag - nessuna codifica |
modules/App/assets/vue-components/fields/field-select.js | 26 | Render select - nessuna codifica |
modules/Content/views/collection/items.php | 149 | Sink 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
}
}'
Un amministratore o editor naviga a /content/collection/items/posts. Il renderer dei tag restituisce la stringa memorizzata, v-html la analizza in un vero elemento ``, l'attributo src falso fallisce e il gestore onerror si attiva.
Entrambi i token sono ora leggibili - il cookie di sessione tramite document.cookie e il JWT CSRF tramite App.csrf / document.documentElement.getAttribute('data-csrf'). Un payload armato esfiltra entrambi:

L'attaccante riproduce il cookie e il token CSRF rubati, ottenendo pieno accesso autenticato come amministratore - e può quindi creare account amministratore, modificare le credenziali o alterare i contenuti.
Un editor con privilegi bassi (o qualsiasi possessore di chiave API con permessi di scrittura) scala a amministratore completo. Il payload è memorizzato e si attiva per ogni amministratore/editor che visualizza l'elenco, rendendolo un compromesso persistente e multi-vittima.
Correzione principale - sanitizzare l'output del render prima che raggiunga v-html usando l'helper esistente 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
Difesa in profondità - rafforzare il cookie di sessione:
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1); // over HTTPS
ini_set('session.cookie_samesite', 'Strict');
HttpOnly da solo è insufficiente - l'XSS può ancora agire nel contesto autenticato del browser della vittima - quindi la codifica dell'output è la correzione essenziale.
| Data | Evento |
|---|---|
| 2026-03-29 | Vulnerabilità segnalata ai manutentori di Cockpit CMS |
| 2026-03-29 | Correzione rilasciata dai manutentori |
| 2026-04-04 | Richiesto CVE |
| 2026-06-23 | CVE-2026-39275 assegnato |
<pub date> | Divulgazione pubblica |
Questo materiale è pubblicato a scopo educativo e difensivo in seguito a una divulgazione coordinata. Utilizza solo contro sistemi di tua proprietà o per i quali hai esplicitamente l'autorizzazione a testare.