
CVE-2026-39275 - Gespeichertes XSS führt zur Kontoübernahme in Cockpit CMS
| CVE ID | CVE-2026-39275 |
| Schwachstelle | Gespeichertes Cross-Site Scripting (XSS) → Kontoübernahme |
| CWE | CWE-79 |
| Betroffen | Cockpit CMS <= 2.13.5 |
| Behoben | d70dc50 |
| CVSS 3.1 | 8.4 (AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:N) |
| Melder | Rohith - Security Consultant @ SecurifyAI |
Eine gespeicherte XSS-Schwachstelle in der Listenansicht der Content-Collections ermöglicht es jedem Benutzer mit Schreibzugriff auf Inhalte (einem API-Schlüssel oder einer authentifizierten Editor-Sitzung), beliebiges JavaScript einzuschleusen, das im Browser jedes Administrators oder Editors ausgeführt wird, der die Elementliste der betroffenen Collection aufruft.
Die Session-Token von Cockpit sind vollständig aus JavaScript erreichbar – das Session-Cookie wird ohne das HttpOnly-Flag gesetzt und das CSRF-JWT ist in der globalen Variable App.csrf sowie im data-csrf-Attribut auf <html> verfügbar. Dadurch kann das injizierte Skript beide Token auslesen und extern erneut abspielen, wodurch der CSRF-Schutz ausgehebelt wird und vollständiges Session-Hijacking sowie eine Kontoübernahme ermöglicht werden.
Die Ausgaben der render()-Funktionen der Felder werden ohne Ausgabekodierung an die v-html-Direktive von Vue übergeben.
| Datei | Zeile(n) | Funktion |
|---|---|---|
modules/App/assets/vue-components/fields/field-tags.js | 25 - 34 | Tags-Renderer – keine Kodierung |
modules/App/assets/vue-components/fields/field-select.js | 26 | Select-Renderer – keine Kodierung |
modules/Content/views/collection/items.php | 149 | v-html-Sink |
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
}
}'
Ein Administrator oder Editor ruft /content/collection/items/posts auf. Der Tags-Renderer gibt den gespeicherten String zurück, v-html parst ihn in ein echtes ``-Element, die ungültige src-Adresse schlägt fehl und der onerror-Handler wird ausgelöst.
Beide Token sind nun auslesbar – das Session-Cookie über document.cookie und das CSRF-JWT über App.csrf / document.documentElement.getAttribute('data-csrf'). Ein schadensfähiger Payload exfiltriert beide:

Der Angreifer spielt das gestohlene Cookie und CSRF-Token erneut ab und erlangt so vollständigen authentifizierten Admin-Zugriff – und kann anschließend Administratorkonten erstellen, Anmeldedaten ändern oder Inhalte modifizieren.
Ein Editor mit geringen Rechten (oder jeder Inhaber eines API-Schlüssels mit Schreibzugriff auf Inhalte) eskaliert zum vollwertigen Administrator. Der Payload wird gespeichert und feuert bei jedem Administrator/Editor, der die Liste aufruft – eine persistente Kompromittierung mehrerer Opfer.
Primärer Fix – Render-Ausgaben bereinigen, bevor sie v-html erreichen, mithilfe der vorhandenen Hilfsfunktion 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
Defense in Depth – das Session-Cookie härten:
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1); // over HTTPS
ini_set('session.cookie_samesite', 'Strict');
HttpOnly allein reicht nicht aus – das XSS kann weiterhin im authentifizierten Browserkontext des Opfers agieren – daher ist die Ausgabekodierung der entscheidende Fix.
| Datum | Ereignis |
|---|---|
| 2026-03-29 | Schwachstelle an die Cockpit-CMS-Maintainer gemeldet |
| 2026-03-29 | Fix von den Maintainern veröffentlicht |
| 2026-04-04 | CVE beantragt |
| 2026-06-23 | CVE-2026-39275 zugewiesen |
<Veröffentlichungsdatum> | Öffentliche Offenlegung |
Dieses Material wird nach koordinierter Offenlegung zu Bildungs- und Verteidigungszwecken veröffentlicht. Verwenden Sie es nur gegen Systeme, die Ihnen gehören oder für deren Test Sie ausdrücklich autorisiert wurden.